CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/DataFormats/Common/interface/LazyGetter.h

Go to the documentation of this file.
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     //Used by ROOT storage
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      //check pointer here and throw if null
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       //check pointer here and throw if null
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     //Used by ROOT storage
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       //Reserve 100,000 to absorb event-by-event fluctuations.
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       //return &(const_cast< RegionIndex<T>& >(*(const_cast< LazyGetter<T>& >(iContainer).begin()+iIndex)).updateLazyGetter(&iContainer));
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