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