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