CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/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   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     //Used by ROOT storage
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      //check pointer here and throw if null
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       //check pointer here and throw if null
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     // This a temporary fix for the bug caused by the bad design
00223     // in EcalUnpackerWorker (used through derived class
00224     // EcalToRecHitLazyUnpacker) and should be removed as soon
00225     // as no longer necessary. Do not use this for anything else.
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     // This a temporary fix for the bug caused by the bad design
00368     // in EcalUnpackerWorker (used through derived class
00369     // EcalToRecHitLazyUnpacker) and should be removed as soon
00370     // as no longer necessary. Do not use this for anything else.
00371     void setEvent(Event const& e) const { unpacker_->setEvent(e); }
00372 
00373     //Used by ROOT storage
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       //Reserve 100,000 to absorb event-by-event fluctuations.
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       //return &(const_cast< RegionIndex<T>& >(*(const_cast< LazyGetter<T>& >(iContainer).begin()+iIndex)).updateLazyGetter(&iContainer));
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