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 "boost/shared_ptr.hpp"
34 
39 
40 namespace edm {
41 
42  //------------------------------------------------------------
43  // Forward declarations
44  template <class T> class DetSetLazyVector;
45 
46  //------------------------------------------------------------
47  // Helper function, to regularize throwing of exceptions.
48  //------------------------------------------------------------
49 
50  namespace dslvdetail
51  {
52  // Throw an edm::Exception with an appropriate message
53  inline
55  {
57  "DetSetLazyVector::operator[] called with index not in collection;\nindex value: ", i);
58  }
59  }
60 
61  namespace dslv {
62  template< typename T>
63  class LazyGetter {
64 public:
65  virtual ~LazyGetter() {}
66  virtual void fill(DetSet<T>&) = 0;
67  };
68  template<typename T>
69  struct LazyAdapter : public std::unary_function<const DetSet<T>&, const DetSet<T>&> {
70  LazyAdapter(boost::shared_ptr<LazyGetter<T> > iGetter): getter_(iGetter) {}
71  const DetSet<T>& operator()(const DetSet<T>& iUpdate) const {
72  if(iUpdate.data.empty() && getter_) {
73  //NOTE: because this is 'updating a cache' we need to cast away the const
74  DetSet<T>& temp = const_cast< DetSet<T>& >(iUpdate);
75  getter_->fill(temp);
76  std::sort(temp.begin(),temp.end());
77  }
78  return iUpdate;
79  }
80 private:
81  boost::shared_ptr<LazyGetter<T> > getter_;
82  };
83  }
84  //------------------------------------------------------------
85  //
86  namespace refhelper {
87  template<typename T>
88  struct FindDetSetForDetSetLazyVector : public std::binary_function<const DetSetLazyVector<T>&, edm::det_id_type, const DetSet<T>*> {
90  typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) const {
91  return &(*(iContainer.find(iIndex)));
92  }
93  };
94  }
95 
96  template <class T>
97  class DetSetLazyVector
98  {
101  BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
102  public:
103 
104  typedef DetSet<T> detset;
106  typedef std::vector<value_type> collection_type;
107 
108  typedef detset const& const_reference;
109 
110  //iterator returns a DetSet<T> instead of a Ref<...>
111  typedef boost::transform_iterator< dslv::LazyAdapter<T>, typename collection_type::const_iterator > const_iterator;
113 
116 
117  // Add the following only if needed.
118  //template <class InputIterator>
119  //DetSetLazyVector(InputIterator b, InputIterator e);
120 
122 
123  DetSetLazyVector(boost::shared_ptr<dslv::LazyGetter<T> > iGetter, const std::vector<det_id_type>& iDets) :
124  sets_(),
125  getter_(iGetter) {
126  sets_.reserve(iDets.size());
127  det_id_type sanityCheck = 0;
128  for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
129  itDetId != itDetIdEnd;
130  ++itDetId) {
131  assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
132  sanityCheck = *itDetId;
133  sets_.push_back(DetSet<T>(*itDetId));
134  }
135  }
136 
137  void swap(DetSetLazyVector& other);
138 
139  // DetSetVector& operator=(DetSetVector const& rhs);
140 
142  bool empty() const;
143 
145  size_type size() const;
146 
147  // Do we need a short-hand method to return the number of T
148  // instances? If so, do we optimize for size (calculate on the
149  // fly) or speed (keep a current cache)?
150 
153  const_iterator find(det_id_type id) const;
154 
159 
161  const_iterator begin() const;
162 
164  const_iterator end() const;
165 
168  //void post_insert();
169 
170  private:
172  boost::shared_ptr<dslv::LazyGetter<T> > getter_;
173  };
174 
175  template <class T>
176  inline
177  void
179  {
180  sets_.swap(other.sets_);
181  std::swap(getter_,other.getter_);
182  }
183 
184  template <class T>
185  inline
186  bool
188  {
189  return sets_.empty();
190  }
191 
192  template <class T>
193  inline
196  {
197  return sets_.size();
198  }
199 
200  template <class T>
201  inline
204  {
205  if(empty()) {
206  dslv::LazyAdapter<T> adapter(getter_);
207  return boost::make_transform_iterator(sets_.end(),adapter);
208  }
209  //NOTE: using collection_type::const_iterator and NOT const_iterator. We do this to avoid calling the
210  // dereferencing operation on const_iterator which would cause the 'lazy update' to happen
211  std::pair<typename collection_type::const_iterator,typename collection_type::const_iterator> p =
212  std::equal_range(sets_.begin(), sets_.end(), id);
213  if (p.first == p.second) {
214  dslv::LazyAdapter<T> adapter(getter_);
215  return boost::make_transform_iterator(sets_.end(),adapter);
216  }
217  // The range indicated by [p.first, p.second) should be exactly of
218  // length 1.
219  assert(std::distance(p.first, p.second) == 1);
220  dslv::LazyAdapter<T> adapter(getter_);
221  return boost::make_transform_iterator(p.first,adapter);
222  }
223 
224  template <class T>
225  inline
228  {
229  // Find the right DetSet, and return a reference to it. Throw if
230  // there is none.
231  const_iterator it = this->find(i);
232  if (it == this->end()) dslvdetail::_throw_range(i);
233  return *it;
234  }
235 
236  template <class T>
237  inline
240  {
241  dslv::LazyAdapter<T> adapter(getter_);
242  return boost::make_transform_iterator(sets_.begin(),adapter);
243  }
244 
245  template <class T>
246  inline
249  {
250  dslv::LazyAdapter<T> adapter(getter_);
251  return boost::make_transform_iterator(sets_.end(),adapter);
252  }
253 
254  // Free swap function
255  template <class T>
256  inline
257  void
259  {
260  a.swap(b);
261  }
262 
263 //specialize behavior of edm::Ref to get access to the 'Det'
264 
265  namespace refhelper {
266  template<typename T>
267  struct FindForDetSetLazyVector : public std::binary_function<const DetSetLazyVector<T>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
269  typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
270  return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
271  }
272  };
273 
274  template<typename T>
277  };
278  }
279 
280  //helper function to make it easier to create a edm::Ref
281 
282  template<class HandleT>
284  makeRefToDetSetLazyVector(const HandleT& iHandle,
285  det_id_type iDetID,
286  typename HandleT::element_type::value_type::const_iterator itIter) {
287  typedef typename HandleT::element_type Vec;
289  typename Vec::const_iterator itFound = iHandle->find(iDetID);
290  index += (itIter- itFound->data.begin());
292  }
293 
294  template<class HandleT>
295  Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
296  makeRefToDetSetLazyVector(const HandleT& iHandle,
297  det_id_type iDetID,
298  typename HandleT::element_type::value_type::iterator itIter) {
299  typedef typename HandleT::element_type Vec;
300  typename Vec::detset::const_iterator itIter2 = itIter;
301  return makeRefToDetSetLazyVector(iHandle,iDetID,itIter2);
302  }
303 }
304 #endif
iterator end()
Definition: DetSet.h:60
BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept)
int i
Definition: DBlmapReader.cc:9
boost::shared_ptr< LazyGetter< T > > getter_
self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex)
collection_type::size_type size_type
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
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)
#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
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
DetSetLazyVector(boost::shared_ptr< dslv::LazyGetter< T > > iGetter, const std::vector< det_id_type > &iDets)
const DetSet< T > & operator()(const DetSet< T > &iUpdate) const
boost::shared_ptr< dslv::LazyGetter< T > > getter_
long double T
const_iterator end() const
Return the off-the-end iterator.
LazyAdapter(boost::shared_ptr< LazyGetter< T > > iGetter)
boost::transform_iterator< dslv::LazyAdapter< T >, typename collection_type::const_iterator > const_iterator