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