00001 #ifndef DataFormats_Common_LazyGetter_h
00002 #define DataFormats_Common_LazyGetter_h
00003
00004 #include <algorithm>
00005 #include <vector>
00006 #include "boost/concept_check.hpp"
00007 #include "boost/iterator/transform_iterator.hpp"
00008 #include "boost/shared_ptr.hpp"
00009 #include "DataFormats/Common/interface/traits.h"
00010 #include "DataFormats/Common/interface/Ref.h"
00011 #include "DataFormats/Common/interface/DetSet.h"
00012 #include "DataFormats/Common/interface/Handle.h"
00013 #include "FWCore/Utilities/interface/EDMException.h"
00014
00015 namespace edm {
00016
00017
00018
00019 template <class T> class LazyAdapter;
00020 template <class T> class LazyGetter;
00021 template <class T> class FindValue;
00022
00023
00024
00025 namespace lazydetail {
00026 inline
00027 void _throw_range(uint32_t region)
00028 {
00029 Exception::throwThis(errors::InvalidReference,
00030 "LazyGetter::"
00031 "find(uint32_t,uint32_t) called with index not in collection;\n"
00032 "index value: ",
00033 region);
00034 }
00035 }
00036
00037
00038 template<class T>
00039 class RegionIndex {
00040
00041 friend class LazyAdapter<T>;
00042
00043 public:
00044
00045 typedef typename std::vector<T>::const_iterator const_iterator;
00046 typedef std::pair<const_iterator,const_iterator> pair_iterator;
00047
00049 RegionIndex();
00050
00052 RegionIndex(uint32_t region, uint32_t start, uint32_t finish, const LazyGetter<T>* theLazyGetter);
00053
00055 uint32_t region() const;
00056
00058 uint32_t start() const;
00059
00061 uint32_t finish() const;
00062
00064 bool unpacked() const;
00065
00067 const_iterator begin() const;
00068
00070 const_iterator end() const;
00071
00073 RegionIndex<T>& updateLazyGetter(const LazyGetter<T>* newLazyGetter);
00074
00076 pair_iterator find(uint32_t id) const;
00077
00078 private:
00079
00081 void start(uint32_t);
00082
00084 void finish(uint32_t);
00085
00087 void unpacked(bool);
00088
00089 uint32_t region_;
00090 uint32_t start_;
00091 uint32_t finish_;
00092 bool unpacked_;
00093 const LazyGetter<T> * getter_;
00094 };
00095
00096
00097
00098 template <class T>
00099 inline
00100 RegionIndex<T>::RegionIndex() :
00101 region_(0),
00102 start_(0),
00103 finish_(0),
00104 unpacked_(false),
00105 getter_(NULL)
00106 {}
00107
00108 template <class T>
00109 inline
00110 RegionIndex<T>::RegionIndex(uint32_t region, uint32_t start, uint32_t finish, const LazyGetter<T>* theLazyGetter) :
00111 region_(region),
00112 start_(start),
00113 finish_(finish),
00114 unpacked_(false),
00115 getter_(theLazyGetter)
00116 {}
00117
00118 template <class T>
00119 inline
00120 uint32_t
00121 RegionIndex<T>::region() const
00122 {
00123 return region_;
00124 }
00125
00126 template <class T>
00127 inline
00128 uint32_t
00129 RegionIndex<T>::start() const
00130 {
00131 return start_;
00132 }
00133
00134 template <class T>
00135 inline
00136 uint32_t RegionIndex<T>::finish() const
00137 {
00138 return finish_;
00139 }
00140
00141 template <class T>
00142 inline
00143 bool
00144 RegionIndex<T>::unpacked() const
00145 {
00146 return unpacked_;
00147 }
00148
00149 template <class T>
00150 inline
00151 void
00152 RegionIndex<T>::start(uint32_t newstart)
00153 {
00154 start_=newstart;
00155 }
00156
00157 template <class T>
00158 inline
00159 void
00160 RegionIndex<T>::finish(uint32_t newfinish)
00161 {
00162 finish_=newfinish;
00163 }
00164
00165 template <class T>
00166 inline
00167 void
00168 RegionIndex<T>::unpacked(bool newunpacked)
00169 {
00170 unpacked_=newunpacked;
00171 }
00172
00173 template <class T>
00174 inline
00175 typename RegionIndex<T>::const_iterator
00176 RegionIndex<T>::begin() const
00177 {
00178
00179 return getter_->begin_record()+start_;
00180 }
00181
00182 template <class T>
00183 inline
00184 typename RegionIndex<T>::const_iterator
00185 RegionIndex<T>::end() const
00186 {
00187
00188 return getter_->begin_record()+finish_;
00189 }
00190
00191 template <class T>
00192 inline
00193 RegionIndex<T>&
00194 RegionIndex<T>::updateLazyGetter(const LazyGetter<T>* newGetter)
00195 {
00196 getter_ = newGetter;
00197 return *this;
00198 }
00199
00200 template <class T>
00201 inline
00202 typename RegionIndex<T>::pair_iterator
00203 RegionIndex<T>::find(uint32_t id) const
00204 {
00205 return std::equal_range(begin(),end(),id);
00206 }
00207
00208
00209
00210 template<typename T>
00211 class LazyUnpacker {
00212 public:
00213 typedef std::vector<T> record_type;
00214 virtual void fill(const uint32_t&, record_type&)=0;
00215 virtual ~LazyUnpacker() {}
00216 };
00217
00218
00219
00220 template<typename T>
00221 class LazyAdapter : public std::unary_function<const RegionIndex<T>&, const RegionIndex<T>& > {
00222 public:
00223
00224 typedef std::vector<T> record_type;
00225
00227 LazyAdapter(const LazyUnpacker<T>*,const record_type*, const LazyGetter<T>*);
00228
00230 const RegionIndex<T>& operator()(const RegionIndex<T>& region) const;
00231
00232 private:
00233 LazyUnpacker<T>* unpacker_;
00234 record_type * record_;
00235 const LazyGetter<T>* getter_;
00236 };
00237
00238 template <class T>
00239 inline
00240 LazyAdapter<T>::LazyAdapter(const LazyUnpacker<T>* iunpacker, const record_type* irecord, const LazyGetter<T>* getter) :
00241 unpacker_(const_cast< LazyUnpacker<T>* >(iunpacker)),
00242 record_(const_cast<record_type*>(irecord)),
00243 getter_(getter) {}
00244
00245 template <class T>
00246 inline
00247 const RegionIndex<T>&
00248 LazyAdapter<T>::operator()(const RegionIndex<T>& index) const
00249 {
00250 RegionIndex<T>& indexref = const_cast< RegionIndex<T>& >(index);
00251 if (!index.unpacked()) {
00252 indexref.start(record_->size());
00253 unpacker_->fill(index.region(),*record_);
00254 indexref.unpacked(true);
00255 indexref.finish(record_->size());
00256 indexref.updateLazyGetter(getter_);
00257 }
00258 return index;
00259 }
00260
00261
00262
00263 template<typename T> class UpdateGetterAdapter : public std::unary_function<const RegionIndex<T>&, const RegionIndex<T>& > {
00264
00265 public:
00266
00268 UpdateGetterAdapter(const LazyGetter<T>*);
00269
00271 const RegionIndex<T>& operator()(const RegionIndex<T>&) const;
00272
00273 private:
00274
00275 const LazyGetter<T>* getter_;
00276 };
00277
00278 template <class T>
00279 inline
00280 UpdateGetterAdapter<T>::UpdateGetterAdapter(const LazyGetter<T>* getter)
00281 : getter_(getter) {}
00282
00283 template <class T>
00284 inline
00285 const RegionIndex<T>&
00286 UpdateGetterAdapter<T>::operator()(const RegionIndex<T>& index) const
00287 {
00288 RegionIndex<T>& indexref = const_cast< RegionIndex<T>& >(index);
00289 indexref.updateLazyGetter(getter_);
00290 return index;
00291 }
00292
00293
00294
00295 template <class T>
00296 class LazyGetter
00297 {
00298
00299 BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
00300
00301 public:
00302
00303 typedef std::vector< RegionIndex<T> > register_type;
00304 typedef std::vector<T> record_type;
00305 typedef boost::transform_iterator< UpdateGetterAdapter<T>, typename register_type::const_iterator > register_iterator;
00306 typedef typename record_type::const_iterator record_iterator;
00307 typedef boost::transform_iterator< LazyAdapter<T>, typename register_type::const_iterator > const_iterator;
00308 typedef Ref< LazyGetter<T>, T, FindValue<T> > value_ref;
00309
00311 LazyGetter();
00312
00314 LazyGetter(uint32_t, const boost::shared_ptr< LazyUnpacker<T> >&);
00315
00317 uint32_t regions() const;
00318
00320 const_iterator find(uint32_t index) const;
00321
00323 const RegionIndex<T>& operator[](uint32_t index) const;
00324
00326 const_iterator begin() const;
00327
00329 const_iterator end() const;
00330
00332 register_iterator begin_nounpack() const;
00333
00335 register_iterator end_nounpack() const;
00336
00339 bool unpacked(uint32_t) const;
00340
00342 record_iterator begin_record() const;
00343
00345 record_iterator end_record() const;
00346
00348 uint32_t size() const;
00349
00351 bool empty() const;
00352
00354 void swap(LazyGetter& other);
00355
00356 private:
00357
00358 boost::shared_ptr< LazyUnpacker<T> > unpacker_;
00359 std::vector<T> record_;
00360 std::vector< RegionIndex<T> > register_;
00361 };
00362
00363 template <class T>
00364 inline
00365 LazyGetter<T>::LazyGetter() : unpacker_(), record_(), register_()
00366 {}
00367
00368 template <class T>
00369 inline
00370 LazyGetter<T>::LazyGetter(uint32_t nregions,const boost::shared_ptr< LazyUnpacker<T> > & unpacker) : unpacker_(unpacker), record_(), register_()
00371 {
00372
00373 record_.reserve(100000);
00374 register_.reserve(nregions);
00375 for (uint32_t iregion=0;iregion<nregions;iregion++) {
00376 register_.push_back(RegionIndex<T>(iregion,0,0,this));
00377 }
00378 }
00379
00380 template <class T>
00381 inline
00382 void
00383 LazyGetter<T>::swap(LazyGetter<T>& other)
00384 {
00385 std::swap(unpacker_,other.unpacker_);
00386 std::swap(record_,other.record_);
00387 std::swap(register_,other.register_);
00388 }
00389
00390 template <class T>
00391 inline
00392 uint32_t
00393 LazyGetter<T>::regions() const
00394 {
00395 return register_.size();
00396 }
00397
00398 template <class T>
00399 inline
00400 typename LazyGetter<T>::const_iterator
00401 LazyGetter<T>::find(uint32_t index) const
00402 {
00403 if (index>=regions()) return end();
00404 typename register_type::const_iterator it = register_.begin()+index;
00405 const LazyAdapter<T> adapter(unpacker_.get(),&record_,this);
00406 return boost::make_transform_iterator(it,adapter);
00407 }
00408
00409 template <class T>
00410 inline
00411 const RegionIndex<T>&
00412 LazyGetter<T>::operator[](uint32_t index) const
00413 {
00414 if (index>=regions()) edm::lazydetail::_throw_range(index);
00415 typename register_type::const_iterator it = register_.begin()+index;
00416 const LazyAdapter<T> adapter(unpacker_.get(),&record_,this);
00417 return *(boost::make_transform_iterator(it,adapter));
00418 }
00419
00420 template <class T>
00421 inline
00422 typename LazyGetter<T>::const_iterator
00423 LazyGetter<T>::begin() const
00424 {
00425 const LazyAdapter<T> adapter(unpacker_.get(),&record_,this);
00426 return boost::make_transform_iterator(register_.begin(),adapter);
00427 }
00428
00429 template <class T>
00430 inline
00431 typename LazyGetter<T>::const_iterator
00432 LazyGetter<T>::end() const
00433 {
00434 const LazyAdapter<T> adapter(unpacker_.get(),&record_,this);
00435 return boost::make_transform_iterator(register_.end(),adapter);
00436 }
00437
00438 template <class T>
00439 inline
00440 typename LazyGetter<T>::register_iterator
00441 LazyGetter<T>::begin_nounpack() const
00442 {
00443 const UpdateGetterAdapter<T> adapter(this);
00444 return boost::make_transform_iterator(register_.begin(),adapter);
00445 }
00446
00447 template <class T>
00448 inline
00449 typename LazyGetter<T>::register_iterator
00450 LazyGetter<T>::end_nounpack() const
00451 {
00452 const UpdateGetterAdapter<T> adapter(this);
00453 return boost::make_transform_iterator(register_.end(),adapter);
00454 }
00455
00456 template <class T>
00457 inline
00458 bool
00459 LazyGetter<T>::unpacked(uint32_t index) const
00460 {
00461 return (index<regions()) ? register_[index].unpacked() : false;
00462 }
00463
00464 template <class T>
00465 inline
00466 typename LazyGetter<T>::record_iterator
00467 LazyGetter<T>::begin_record() const
00468 {
00469 return record_.begin();
00470 }
00471
00472 template <class T>
00473 inline
00474 typename LazyGetter<T>::record_iterator
00475 LazyGetter<T>::end_record() const
00476 {
00477 return record_.end();
00478 }
00479
00480 template <class T>
00481 inline
00482 uint32_t
00483 LazyGetter<T>::size() const
00484 {
00485 return record_.size();
00486 }
00487
00488 template <class T>
00489 inline
00490 bool
00491 LazyGetter<T>::empty() const
00492 {
00493 return record_.empty();
00494 }
00495
00496 template <class T>
00497 inline
00498 void
00499 swap(LazyGetter<T>& a, LazyGetter<T>& b)
00500 {
00501 a.swap(b);
00502 }
00503
00504
00505
00506
00507
00508
00509 template<typename T> struct FindRegion : public std::binary_function< const LazyGetter<T>&, const uint32_t, const RegionIndex<T>* > {
00510 typename FindRegion<T>::result_type operator()(typename FindRegion<T>::first_argument_type iContainer, typename FindRegion<T>::second_argument_type iIndex) {
00511
00512 return &(const_cast< RegionIndex<T>& >(*(const_cast< LazyGetter<T>& >(iContainer).begin()+iIndex)));
00513 }
00514 };
00515
00516
00517
00518 template<typename T> struct FindValue : public std::binary_function< const LazyGetter<T>&, const uint32_t, const T* > {
00519 typename FindValue<T>::result_type operator()(typename FindValue<T>::first_argument_type container, typename FindValue<T>::second_argument_type index) const {return &*(container.begin_record()+index);}
00520 };
00521
00522
00523
00524 template<typename T> Ref< LazyGetter<T>, T, FindValue<T> >
00525 makeRefToLazyGetter(const Handle< LazyGetter<T> >& handle, const uint32_t index) {return Ref< LazyGetter<T>, T, FindValue<T> >(handle,index);}
00526
00527
00528
00529 }
00530
00531 #endif
00532
00533
00534