CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:29:18 2009 for CMSSW by  doxygen 1.5.4