CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DetSetLazyVector.h
Go to the documentation of this file.
1 #ifndef DataFormats_Common_DetSetLazyVector_h
2 #define DataFormats_Common_DetSetLazyVector_h
3 
4 /*----------------------------------------------------------------------
5 
6 DetSetLazyVector: A collection of homogeneous objects that can be used for
7 an EDProduct. DetSetVector is *not* designed for use as a base class
8 (it has no virtual functions).
9 
10 DetSetVector<T> contains a vector<DetSet<T> >, sorted on DetId, and
11 provides fast (O(log n)) lookups, but only O(n) insertion.
12 
13 It provides an interface such that EdmRef2 can directly reference, and
14 provide access to, individual T objects.
15 
16 The collection appears to the user as if it were a sequence of
17 DetSet<T>; e.g., operator[] returns a DetSet<T>&. However, the
18 argument to operator[] specifies the (DetId) identifier of the vector
19 to be returned, *not* the ordinal number of the T to be returned.
20 
21  ------------------
22  It is critical that users DO NOT MODIFY the id data member of a
23  DetSet object in a DetSetVector.
24  ------------------
25 
26 ----------------------------------------------------------------------*/
27 
28 #include <algorithm>
29 #include <vector>
30 
31 #include "boost/concept_check.hpp"
32 #include "boost/iterator/transform_iterator.hpp"
33 #include <memory>
34 
40 
41 namespace edm {
42 
43  //------------------------------------------------------------
44  // Forward declarations
45  template <class T> class DetSetLazyVector;
46 
47  //------------------------------------------------------------
48  // Helper function, to regularize throwing of exceptions.
49  //------------------------------------------------------------
50 
51  namespace dslvdetail
52  {
53  // Throw an edm::Exception with an appropriate message
54  inline
56  {
58  "DetSetLazyVector::operator[] called with index not in collection;\nindex value: ", i);
59  }
60  }
61 
62  namespace dslv {
63  template< typename T>
64  class LazyGetter {
65 public:
66  virtual ~LazyGetter() {}
67  virtual void fill(DetSet<T>&) = 0;
68  };
69  template<typename T>
70  struct LazyAdapter : public std::unary_function<const DetSet<T>&, const DetSet<T>&> {
71  LazyAdapter(std::shared_ptr<LazyGetter<T> > iGetter): getter_(iGetter) {}
72  const DetSet<T>& operator()(const DetSet<T>& iUpdate) const {
73  if(iUpdate.data.empty() && getter_) {
74  //NOTE: because this is 'updating a cache' we need to cast away the const
75  DetSet<T>& temp = const_cast< DetSet<T>& >(iUpdate);
76  getter_->fill(temp);
77  std::sort(temp.begin(),temp.end());
78  }
79  return iUpdate;
80  }
81 private:
82  std::shared_ptr<LazyGetter<T> > getter_;
83  };
84  }
85  //------------------------------------------------------------
86  //
87  namespace refhelper {
88  template<typename T>
89  struct FindDetSetForDetSetLazyVector : public std::binary_function<const DetSetLazyVector<T>&, edm::det_id_type, const DetSet<T>*> {
91  typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) const {
92  return &(*(iContainer.find(iIndex)));
93  }
94  };
95  }
96 
97  template <class T>
98  class DetSetLazyVector
99  {
102  BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
103  public:
104 
105  typedef DetSet<T> detset;
107  typedef std::vector<value_type> collection_type;
108 
109  typedef detset const& const_reference;
110 
111  //iterator returns a DetSet<T> instead of a Ref<...>
112  typedef boost::transform_iterator< dslv::LazyAdapter<T>, typename collection_type::const_iterator > const_iterator;
114 
117 
118  // Add the following only if needed.
119  //template <class InputIterator>
120  //DetSetLazyVector(InputIterator b, InputIterator e);
121 
123 
124  DetSetLazyVector(std::shared_ptr<dslv::LazyGetter<T> > iGetter, const std::vector<det_id_type>& iDets) :
125  sets_(),
126  getter_(iGetter) {
127  sets_.reserve(iDets.size());
128  det_id_type sanityCheck = 0;
129  for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
130  itDetId != itDetIdEnd;
131  ++itDetId) {
132  assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
133  sanityCheck = *itDetId;
134  sets_.push_back(DetSet<T>(*itDetId));
135  }
136  }
137 
138  void swap(DetSetLazyVector& other);
139 
140  // DetSetVector& operator=(DetSetVector const& rhs);
141 
143  bool empty() const;
144 
146  size_type size() const;
147 
148  // Do we need a short-hand method to return the number of T
149  // instances? If so, do we optimize for size (calculate on the
150  // fly) or speed (keep a current cache)?
151 
154  const_iterator find(det_id_type id) const;
155 
160 
162  const_iterator begin() const;
163 
165  const_iterator end() const;
166 
169  //void post_insert();
170 
171  private:
173  std::shared_ptr<dslv::LazyGetter<T> > getter_;
174  };
175 
176  template <class T>
177  inline
178  void
180  {
181  sets_.swap(other.sets_);
182  std::swap(getter_,other.getter_);
183  }
184 
185  template <class T>
186  inline
187  bool
189  {
190  return sets_.empty();
191  }
192 
193  template <class T>
194  inline
197  {
198  return sets_.size();
199  }
200 
201  template <class T>
202  inline
205  {
206  if(empty()) {
207  dslv::LazyAdapter<T> adapter(getter_);
208  return boost::make_transform_iterator(sets_.end(),adapter);
209  }
210  //NOTE: using collection_type::const_iterator and NOT const_iterator. We do this to avoid calling the
211  // dereferencing operation on const_iterator which would cause the 'lazy update' to happen
212  std::pair<typename collection_type::const_iterator,typename collection_type::const_iterator> p =
213  std::equal_range(sets_.begin(), sets_.end(), id);
214  if (p.first == p.second) {
215  dslv::LazyAdapter<T> adapter(getter_);
216  return boost::make_transform_iterator(sets_.end(),adapter);
217  }
218  // The range indicated by [p.first, p.second) should be exactly of
219  // length 1.
220  assert(std::distance(p.first, p.second) == 1);
221  dslv::LazyAdapter<T> adapter(getter_);
222  return boost::make_transform_iterator(p.first,adapter);
223  }
224 
225  template <class T>
226  inline
229  {
230  // Find the right DetSet, and return a reference to it. Throw if
231  // there is none.
232  const_iterator it = this->find(i);
233  if (it == this->end()) dslvdetail::_throw_range(i);
234  return *it;
235  }
236 
237  template <class T>
238  inline
241  {
242  dslv::LazyAdapter<T> adapter(getter_);
243  return boost::make_transform_iterator(sets_.begin(),adapter);
244  }
245 
246  template <class T>
247  inline
250  {
251  dslv::LazyAdapter<T> adapter(getter_);
252  return boost::make_transform_iterator(sets_.end(),adapter);
253  }
254 
255  // Free swap function
256  template <class T>
257  inline
258  void
260  {
261  a.swap(b);
262  }
263 
264 //specialize behavior of edm::Ref to get access to the 'Det'
265 
266  namespace refhelper {
267  template<typename T>
268  struct FindForDetSetLazyVector : public std::binary_function<const DetSetLazyVector<T>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
270  typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
271  return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
272  }
273  };
274 
275  template<typename T>
278  };
279  }
280 
281  //helper function to make it easier to create a edm::Ref
282 
283  template<class HandleT>
285  makeRefToDetSetLazyVector(const HandleT& iHandle,
286  det_id_type iDetID,
287  typename HandleT::element_type::value_type::const_iterator itIter) {
288  typedef typename HandleT::element_type Vec;
290  typename Vec::const_iterator itFound = iHandle->find(iDetID);
291  index += (itIter- itFound->data.begin());
293  }
294 
295  template<class HandleT>
296  Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
297  makeRefToDetSetLazyVector(const HandleT& iHandle,
298  det_id_type iDetID,
299  typename HandleT::element_type::value_type::iterator itIter) {
300  typedef typename HandleT::element_type Vec;
301  typename Vec::detset::const_iterator itIter2 = itIter;
302  return makeRefToDetSetLazyVector(iHandle,iDetID,itIter2);
303  }
304 }
305 #endif
iterator end()
Definition: DetSet.h:60
BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept)
int i
Definition: DBlmapReader.cc:9
self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex)
collection_type::size_type size_type
DetSetLazyVector(std::shared_ptr< dslv::LazyGetter< T > > iGetter, const std::vector< det_id_type > &iDets)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
void _throw_range(det_id_type i)
uint16_t size_type
std::shared_ptr< LazyGetter< T > > getter_
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:116
static void throwThis(Code category, char const *message0="", char const *message1="", char const *message2="", char const *message3="", char const *message4="")
const_reference operator[](det_id_type i) const
size_type size() const
Return the number of contained DetSets.
void swap(DetSetLazyVector &other)
const_iterator begin() const
Return an iterator to the first DetSet.
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
std::shared_ptr< dslv::LazyGetter< T > > getter_
#define end
Definition: vmac.h:37
self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) const
const_iterator find(det_id_type id) const
virtual void fill(DetSet< T > &)=0
detset const & const_reference
iterator begin()
Definition: DetSet.h:59
Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type > makeRefToDetSetLazyVector(const HandleT &iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::const_iterator itIter)
uint32_t det_id_type
Definition: DetSet.h:21
LazyAdapter(std::shared_ptr< LazyGetter< T > > iGetter)
std::vector< value_type > collection_type
double b
Definition: hdecay.h:120
collection_type data
Definition: DetSet.h:78
bool empty() const
Return true if we contain no DetSets.
double a
Definition: hdecay.h:121
const DetSet< T > & operator()(const DetSet< T > &iUpdate) const
long double T
const_iterator end() const
Return the off-the-end iterator.
boost::transform_iterator< dslv::LazyAdapter< T >, typename collection_type::const_iterator > const_iterator