CMS 3D CMS Logo

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