CMS 3D CMS Logo

MultiAssociation.h
Go to the documentation of this file.
1 #ifndef DataFormats_Common_MultiAssociation_h
2 #define DataFormats_Common_MultiAssociation_h
3 /* \class MultiAssociation
4  *
5  * \author Giovanni Petrucciani, SNS Pisa and CERN PH-CMG
6  *
7  * One-to-Many variant of edm::Association<C> / edm::ValueMap<T>,
8  *
9  * Given a key, it will return a range of iterators within a collection (fast access), or collection by value (slow access mode)
10  *
11  * The range of iterators is handled through boost::sub_range, so it should feel like a collection:
12  * 1) it has a '::const_iterator', a 'begin()' and an 'end()'
13  * 2) it has a 'size()' and an 'empty()'
14  * 3) it has a 'front()', 'back()'
15  * 4) it works as an array (i.e. you can use range[index] to pick an element)
16  * 5) if your MultiAssociation is not const, you can modify the values associated to each key
17  * (but you can't push_back new values for a given key)
18  * ( details at http://www.boost.org/doc/libs/1_37_0/libs/range/doc/utility_class.html#sub_range )
19  *
20  * The collection can be a RefVector<C> (to work a la edm::Association<C>), a std::vector<T> (to work a la ValueMap<T>), a PtrVector<T>...
21  * The collection must be compatible with sub_range and support a few other features. Usually you need:
22  * - that it has a default constructor
23  * - that it has a const_iterator, and "begin() const" returns such const_iterator.
24  * - that it has an iterator, and "begin()" returns such iterator (note: it doesn't have to be writable, it can be const as well)
25  * - that it has a swap method
26  * - that 'begin() + offset' is legal (and fast, otherwise this thing is will be awfully slow)
27  * - that you can push_back on a C the * of a C::const_iterator. Namely this should be legal
28  * <code>
29  * C::const_iterator it = ..something..
30  * C someOtherC = ...
31  * someOtherC.push_back(*it);
32  * </code>
33  *
34  * It can be filled through a FastFiller or a LazyFiller.
35  * FastFiller is probably faster, but has many constraints:
36  * - you must fill only one product id at time
37  * - you must fill items in strict key order
38  * - there is no way to abort a filling operation
39  * Try LazyFiller first, unless you're doing some sort of batch task that satisfies the FastFiller requirements
40  *
41  * It stores:
42  * - for each collection of keys: a product id and an offset
43  * - for each key (even those not mapped to any value): one offset
44  * - for each value: one value
45  * With respect to ValueMap / Association, there is one extra int32 for each key (but we don't store null values)
46  *
47  * Its backbone is given by edm::helper::IndexRangeAssociation, that maps keys to ranges, and is not templated.
48  *
49  */
50 
51 #include <vector>
52 #include <map>
53 #include <memory>
54 #include <boost/range.hpp>
57 
58 namespace edm {
59  namespace helper {
64 
72  public:
73  typedef std::pair<unsigned int, unsigned int> range;
74 
76 
79  template <typename RefKey>
80  range operator[](const RefKey &r) const {
81  return get(r.id(), r.key());
82  }
83 
86  range get(const edm::ProductID &id, unsigned int t) const;
87 
89  bool contains(ProductID id) const;
90 
92  unsigned int size() const { return ref_offsets_.empty() ? 0 : ref_offsets_.size() - 1; }
93 
95  bool empty() const { return ref_offsets_.empty(); }
96 
101  class FastFiller {
102  public:
103  FastFiller(const FastFiller &) = delete;
104  FastFiller &operator=(const FastFiller &) = delete;
105 
108 
110  ~FastFiller();
111 
113  template <typename RefKey>
114  void insert(const RefKey &r, unsigned int startingOffset, unsigned int size) {
115  insert(r.id(), r.key(), startingOffset, size);
116  }
117 
119  void insert(edm::ProductID id, unsigned int key, unsigned int startingOffset, unsigned int size);
120 
121  private:
123  const ProductID id_;
124  unsigned int start_, end_; // indices into assoc_.ref_offsets_ (end_ points to the end marker, so it's valid)
126  int lastKey_;
127  }; // FastFiller
128  friend class FastFiller;
129 
131 
132  static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where);
133 
134  private:
135  typedef std::pair<edm::ProductID, unsigned int> id_off_pair;
136  typedef std::vector<id_off_pair> id_offset_vector; // sorted by product id
137  typedef std::vector<int> offset_vector;
140 
141  bool isFilling_; // transient, to check no two fillers exist at the same time
142  struct IDComparator {
143  bool operator()(const id_off_pair &p, const edm::ProductID &id) const { return p.first < id; }
144  }; // IDComparator
145  };
146 
147  // Free swap function
148  inline void swap(IndexRangeAssociation &lhs, IndexRangeAssociation &rhs) { lhs.swap(rhs); }
149 
150  } // namespace helper
151 
152  template <typename C>
154  public:
155  typedef C Collection;
156  typedef boost::sub_range<const Collection> const_range;
157  typedef boost::sub_range<Collection> range;
158 
160 
162  template <typename RefKey>
163  const_range operator[](const RefKey &r) const {
164  return get(r.id(), r.key());
165  }
166  // ---- and the non-const sister
168  template <typename RefKey>
169  range operator[](const RefKey &r) {
170  return get(r.id(), r.key());
171  }
172 
174  template <typename RefKey>
175  Collection getValues(const RefKey &r) const {
176  return getValues(r.id(), r.key());
177  }
178 
180  bool contains(const edm::ProductID &id) const { return indices_.contains(id); }
181 
183  const_range get(const edm::ProductID &id, unsigned int t) const;
184  // ---- and the non-const sister
186  range get(const edm::ProductID &id, unsigned int t);
187 
189  Collection getValues(const edm::ProductID &id, unsigned int t) const;
190 
192  indices_.swap(other.indices_);
193  data_.swap(other.data_);
194  }
195 
197  unsigned int dataSize() const { return data_.size(); }
198 
200  unsigned int size() const { return indices_.size(); }
201 
203  bool empty() const { return indices_.empty(); }
204 
209  class FastFiller {
210  public:
211  template <typename HandleType>
214 
217 
219 
221  template <typename KeyRef>
222  void setValues(const KeyRef &k, const Collection &refs) {
223  setValues(k.id(), k.key(), refs);
224  }
225 
227  void setValues(const edm::ProductID &id, unsigned int key, const Collection &refs);
228 
229  private:
232  std::shared_ptr<IndexFiller> indexFiller_;
233 
234  }; // FastFiller
235  friend class FastFiller;
236 
237  template <typename HandleType>
238  FastFiller fastFiller(const HandleType &handle) {
239  return FastFiller(*this, handle);
240  }
241 
247  class LazyFiller {
248  public:
249  template <typename HandleType>
250  LazyFiller(MultiAssociation &assoc, const HandleType &handle, bool fillOnExit = false)
251  : assoc_(assoc),
252  id_(handle.id()),
253  size_(handle->size()),
254  tempValues_(new TempValues()),
255  fillOnExit_(fillOnExit) {}
256  ~LazyFiller() noexcept(false) {
257  if (fillOnExit_)
258  fill();
259  }
260 
265  void fill() noexcept(false);
266 
268  void setFillOnExit(bool fillOnExit) { fillOnExit_ = fillOnExit; }
269 
271  template <typename KeyRef>
272  void setValues(const KeyRef &k, const Collection &refs);
273 
276  template <typename KeyRef>
277  void swapValues(const KeyRef &k, Collection &refs);
278 
279  private:
280  typedef std::map<unsigned int, Collection> TempValues;
283  unsigned int size_;
284  std::shared_ptr<TempValues> tempValues_;
286  }; // LazyFiller
287  friend class LazyFiller;
288 
289  template <typename HandleType>
290  LazyFiller lazyFiller(const HandleType &h, bool fillOnExit = false) {
291  return LazyFiller(*this, h, fillOnExit);
292  }
293 
294  //Used by ROOT storage
296 
297  private:
298  typedef helper::IndexRangeAssociation Indices;
301 
302  }; // class
303 
304  // Free swap function
305  template <typename C>
306  inline void swap(MultiAssociation<C> &lhs, MultiAssociation<C> &rhs) {
307  lhs.swap(rhs);
308  }
309 
310  //============= IMPLEMENTATION OF THE METHODS =============
311  template <typename C>
313  Indices::range idxrange = indices_.get(id, key);
314  return const_range(data_.begin() + idxrange.first, data_.begin() + idxrange.second);
315  }
316 
317  template <typename C>
319  Indices::range idxrange = indices_.get(id, key);
320  return range(data_.begin() + idxrange.first, data_.begin() + idxrange.second);
321  }
322 
323  template <typename C>
325  unsigned int key) const {
326  Collection ret;
327  const_range values = get(id, key);
328  for (typename const_range::const_iterator it = values.begin(), ed = values.end(); it != ed; ++it) {
329  ret.push_back(*it);
330  }
331  return ret;
332  }
333 
334  template <typename C>
335  void MultiAssociation<C>::FastFiller::setValues(const edm::ProductID &id, unsigned int key, const Collection &vals) {
336  indexFiller_->insert(id, key, assoc_.data_.size(), vals.size());
337  for (typename Collection::const_iterator it = vals.begin(), ed = vals.end(); it != ed; ++it) {
338  assoc_.data_.push_back(*it);
339  }
340  }
341 
342  template <typename C>
343  template <typename KeyRef>
344  void MultiAssociation<C>::LazyFiller::setValues(const KeyRef &k, const Collection &vals) {
345  if (k.id() != id_)
346  Indices::throwUnexpectedProductID(k.id(), id_, "LazyFiller::insert");
347  (*tempValues_)[k.key()] = vals;
348  }
349 
350  template <typename C>
351  template <typename KeyRef>
353  if (k.id() != id_)
354  Indices::throwUnexpectedProductID(k.id(), id_, "LazyFiller::insert");
355  vals.swap((*tempValues_)[k.key()]);
356  }
357 
358  template <typename C>
360  if (id_ != ProductID()) { // protection against double filling
361  typename MultiAssociation<C>::FastFiller filler(assoc_, id_, size_);
362  for (typename TempValues::const_iterator it = tempValues_->begin(), ed = tempValues_->end(); it != ed; ++it) {
363  filler.setValues(id_, it->first, it->second);
364  }
365  id_ = ProductID(); // protection against double filling
366  }
367  }
368 
369 } // namespace edm
370 
371 #endif
runTheMatrix.ret
ret
prodAgent to be discontinued
Definition: runTheMatrix.py:367
edm::helper::IndexRangeAssociation::range
std::pair< unsigned int, unsigned int > range
Definition: MultiAssociation.h:73
edm::helper::swap
void swap(IndexRangeAssociation &lhs, IndexRangeAssociation &rhs)
Definition: MultiAssociation.h:148
edm::helper::IndexRangeAssociation::IDComparator
Definition: MultiAssociation.h:142
edm::MultiAssociation::FastFiller
friend class FastFiller
Definition: MultiAssociation.h:235
edm::helper::IndexRangeAssociation
Definition: MultiAssociation.h:71
edm::helper::IndexRangeAssociation::FastFiller::start_
unsigned int start_
Definition: MultiAssociation.h:124
funct::false
false
Definition: Factorize.h:29
edm::MultiAssociation::LazyFiller::~LazyFiller
~LazyFiller() noexcept(false)
Definition: MultiAssociation.h:256
edm::MultiAssociation::getValues
Collection getValues(const RefKey &r) const
Get a copy of the values for this key (slow!)
Definition: MultiAssociation.h:175
edm::helper::IndexRangeAssociation::FastFiller::lastKey_
int lastKey_
last key used to fill (to check that the new key must be strictly greater than lastKey_)
Definition: MultiAssociation.h:126
edm::helper::IndexRangeAssociation::FastFiller::id_
const ProductID id_
Definition: MultiAssociation.h:123
patZpeak.handle
handle
Definition: patZpeak.py:23
edm::MultiAssociation::LazyFiller::swapValues
void swapValues(const KeyRef &k, Collection &refs)
Definition: MultiAssociation.h:352
edm::helper::IndexRangeAssociation::id_off_pair
std::pair< edm::ProductID, unsigned int > id_off_pair
Definition: MultiAssociation.h:135
edm
HLT enums.
Definition: AlignableModifier.h:19
AlCaHLTBitMon_ParallelJobs.p
p
Definition: AlCaHLTBitMon_ParallelJobs.py:153
edm::MultiAssociation::lazyFiller
LazyFiller lazyFiller(const HandleType &h, bool fillOnExit=false)
Definition: MultiAssociation.h:290
edm::helper::IndexRangeAssociation::swap
void swap(IndexRangeAssociation &other)
Definition: MultiAssociation.cc:35
edm::helper::IndexRangeAssociation::FastFiller::~FastFiller
~FastFiller()
When the FastFiller goes out of scope, it unlocks the map so you can make a new one.
Definition: MultiAssociation.cc:73
edm::MultiAssociation::LazyFiller::LazyFiller
LazyFiller(MultiAssociation &assoc, const HandleType &handle, bool fillOnExit=false)
Definition: MultiAssociation.h:250
edm::MultiAssociation::LazyFiller::id_
ProductID id_
Definition: MultiAssociation.h:282
edm::MultiAssociation::dataSize
unsigned int dataSize() const
Returns the number of values.
Definition: MultiAssociation.h:197
edm::helper::IndexRangeAssociation::id_offsets_
id_offset_vector id_offsets_
Definition: MultiAssociation.h:138
newFWLiteAna.found
found
Definition: newFWLiteAna.py:118
edm::MultiAssociation::range
boost::sub_range< Collection > range
Definition: MultiAssociation.h:157
edm::MultiAssociation::LazyFiller
Definition: MultiAssociation.h:247
trackingPlots.assoc
assoc
Definition: trackingPlots.py:184
edm::helper::IndexRangeAssociation::FastFiller::insert
void insert(const RefKey &r, unsigned int startingOffset, unsigned int size)
Sets the starting offset for this key.
Definition: MultiAssociation.h:114
edm::helper::IndexRangeAssociation::throwUnexpectedProductID
static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where)
Definition: MultiAssociation.cc:119
edm::MultiAssociation::FastFiller
Definition: MultiAssociation.h:209
edm::MultiAssociation::LazyFiller::fillOnExit_
bool fillOnExit_
Definition: MultiAssociation.h:285
edm::helper::IndexRangeAssociation::id_offset_vector
std::vector< id_off_pair > id_offset_vector
Definition: MultiAssociation.h:136
edm::helper::IndexRangeAssociation::empty
bool empty() const
True if it's empty (no keys)
Definition: MultiAssociation.h:95
contentValuesCheck.values
values
Definition: contentValuesCheck.py:38
edm::MultiAssociation::Collection
C Collection
Definition: MultiAssociation.h:155
edm::helper::IndexRangeAssociation::FastFiller::end_
unsigned int end_
Definition: MultiAssociation.h:124
edm::MultiAssociation::FastFiller::~FastFiller
~FastFiller()
Definition: MultiAssociation.h:218
ProductID.h
edm::MultiAssociation
Definition: MultiAssociation.h:153
edm::MultiAssociation::LazyFiller::TempValues
std::map< unsigned int, Collection > TempValues
Definition: MultiAssociation.h:280
trackingPlots.other
other
Definition: trackingPlots.py:1467
CMS_CLASS_VERSION
#define CMS_CLASS_VERSION(_version_)
Definition: CMS_CLASS_VERSION.h:30
edm::helper::IndexRangeAssociation::IndexRangeAssociation
IndexRangeAssociation()
Definition: MultiAssociation.h:75
edm::helper::IndexRangeAssociation::size
unsigned int size() const
Size of this collection (number of keys)
Definition: MultiAssociation.h:92
h
dqmdumpme.k
k
Definition: dqmdumpme.py:60
edm::helper::IndexRangeAssociation::FastFiller::operator=
FastFiller & operator=(const FastFiller &)=delete
edm::helper::IndexRangeAssociation::offset_vector
std::vector< int > offset_vector
Definition: MultiAssociation.h:137
edm::MultiAssociation::LazyFiller::setValues
void setValues(const KeyRef &k, const Collection &refs)
Sets the Collection values associated to this key, making copies of those in refs.
Definition: MultiAssociation.h:344
edm::MultiAssociation::size
unsigned int size() const
Returns the number of keys.
Definition: MultiAssociation.h:200
edm::MultiAssociation::LazyFiller::size_
unsigned int size_
Definition: MultiAssociation.h:283
edm::MultiAssociation::FastFiller::FastFiller
FastFiller(MultiAssociation &assoc, const HandleType &handle)
Definition: MultiAssociation.h:212
trigObjTnPSource_cfi.filler
filler
Definition: trigObjTnPSource_cfi.py:21
edm::MultiAssociation::fastFiller
FastFiller fastFiller(const HandleType &handle)
Definition: MultiAssociation.h:238
helper
Definition: helper.py:1
edm::helper::IndexRangeAssociation::ref_offsets_
offset_vector ref_offsets_
Definition: MultiAssociation.h:139
edm::MultiAssociation::FastFiller::assoc_
MultiAssociation & assoc_
Definition: MultiAssociation.h:230
edm::MultiAssociation::FastFiller::FastFiller
FastFiller(MultiAssociation &assoc, edm::ProductID id, unsigned int size)
Definition: MultiAssociation.h:215
svgfig.template
def template(fileName, svg, replaceme="REPLACEME")
Definition: svgfig.py:521
edm::MultiAssociation::LazyFiller::tempValues_
std::shared_ptr< TempValues > tempValues_
Definition: MultiAssociation.h:284
alignCSCRings.r
r
Definition: alignCSCRings.py:93
edm::helper::IndexRangeAssociation::operator[]
range operator[](const RefKey &r) const
Definition: MultiAssociation.h:80
edm::helper::IndexRangeAssociation::IDComparator::operator()
bool operator()(const id_off_pair &p, const edm::ProductID &id) const
Definition: MultiAssociation.h:143
edm::MultiAssociation::indices_
Indices indices_
Definition: MultiAssociation.h:299
CMS_CLASS_VERSION.h
edm::MultiAssociation::FastFiller::setValues
void setValues(const KeyRef &k, const Collection &refs)
Sets the Collection values associated to this key, making copies of those in refs.
Definition: MultiAssociation.h:222
gen::C
C
Definition: PomwigHadronizer.cc:78
edm::MultiAssociation::LazyFiller::fill
void fill() noexcept(false)
Definition: MultiAssociation.h:359
edm::MultiAssociation::LazyFiller::setFillOnExit
void setFillOnExit(bool fillOnExit)
If set to true, the LazyFiller wil call 'fill()' when it goes out of scope.
Definition: MultiAssociation.h:268
triggerObjects_cff.id
id
Definition: triggerObjects_cff.py:31
edm::MultiAssociation::FastFiller::IndexFiller
edm::helper::IndexRangeAssociation::FastFiller IndexFiller
Definition: MultiAssociation.h:231
edm::MultiAssociation::MultiAssociation
MultiAssociation()
Definition: MultiAssociation.h:159
edm::MultiAssociation::contains
bool contains(const edm::ProductID &id) const
True if there are keys from this product id.
Definition: MultiAssociation.h:180
edm::MultiAssociation::FastFiller::indexFiller_
std::shared_ptr< IndexFiller > indexFiller_
Definition: MultiAssociation.h:232
edm::MultiAssociation::data_
Collection data_
Definition: MultiAssociation.h:300
edm::helper::IndexRangeAssociation::FastFiller::assoc_
IndexRangeAssociation & assoc_
Definition: MultiAssociation.h:122
edm::MultiAssociation::operator[]
const_range operator[](const RefKey &r) const
Get a range of values for this key (fast)
Definition: MultiAssociation.h:163
edm::helper::IndexRangeAssociation::FastFiller::FastFiller
FastFiller(const FastFiller &)=delete
edm::MultiAssociation::LazyFiller
friend class LazyFiller
Definition: MultiAssociation.h:287
edm::MultiAssociation::get
const_range get(const edm::ProductID &id, unsigned int t) const
Get a range of values for this product id and index (fast)
Definition: MultiAssociation.h:312
edm::helper::IndexRangeAssociation::isFilling_
bool isFilling_
Definition: MultiAssociation.h:141
edm::helper::IndexRangeAssociation::FastFiller
Definition: MultiAssociation.h:101
submitPVValidationJobs.t
string t
Definition: submitPVValidationJobs.py:644
crabWrapper.key
key
Definition: crabWrapper.py:19
edm::helper::IndexRangeAssociation::contains
bool contains(ProductID id) const
True if this IndexRangeAssociation has info for this product id.
Definition: MultiAssociation.cc:29
edm::MultiAssociation::LazyFiller::assoc_
MultiAssociation & assoc_
Definition: MultiAssociation.h:281
edm::ProductID
Definition: ProductID.h:27
edm::MultiAssociation::swap
void swap(MultiAssociation &other)
Definition: MultiAssociation.h:191
edm::MultiAssociation::const_range
boost::sub_range< const Collection > const_range
Definition: MultiAssociation.h:156
edm::helper::IndexRangeAssociation::get
range get(const edm::ProductID &id, unsigned int t) const
Definition: MultiAssociation.cc:9
edm::MultiAssociation::empty
bool empty() const
Returns true if there are no keys.
Definition: MultiAssociation.h:203
edm::MultiAssociation::operator[]
range operator[](const RefKey &r)
Get a range of values for this key (fast)
Definition: MultiAssociation.h:169