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/utility.hpp>
55 #include <boost/range.hpp>
58 
59 namespace edm {
60  namespace helper {
65 
73  public:
74  typedef std::pair<unsigned int, unsigned int> range;
75 
77 
80  template <typename RefKey>
81  range operator[](const RefKey &r) const {
82  return get(r.id(), r.key());
83  }
84 
87  range get(const edm::ProductID &id, unsigned int t) const;
88 
90  bool contains(ProductID id) const;
91 
93  unsigned int size() const { return ref_offsets_.empty() ? 0 : ref_offsets_.size() - 1; }
94 
96  bool empty() const { return ref_offsets_.empty(); }
97 
102  class FastFiller : boost::noncopyable {
103  public:
106 
108  ~FastFiller();
109 
111  template <typename RefKey>
112  void insert(const RefKey &r, unsigned int startingOffset, unsigned int size) {
113  insert(r.id(), r.key(), startingOffset, size);
114  }
115 
117  void insert(edm::ProductID id, unsigned int key, unsigned int startingOffset, unsigned int size);
118 
119  private:
121  const ProductID id_;
122  unsigned int start_, end_; // indices into assoc_.ref_offsets_ (end_ points to the end marker, so it's valid)
124  int lastKey_;
125  }; // FastFiller
126  friend class FastFiller;
127 
129 
130  static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where);
131 
132  private:
133  typedef std::pair<edm::ProductID, unsigned int> id_off_pair;
134  typedef std::vector<id_off_pair> id_offset_vector; // sorted by product id
135  typedef std::vector<int> offset_vector;
138 
139  bool isFilling_; // transient, to check no two fillers exist at the same time
140  struct IDComparator {
141  bool operator()(const id_off_pair &p, const edm::ProductID &id) const { return p.first < id; }
142  }; // IDComparator
143  };
144 
145  // Free swap function
146  inline void swap(IndexRangeAssociation &lhs, IndexRangeAssociation &rhs) { lhs.swap(rhs); }
147 
148  } // namespace helper
149 
150  template <typename C>
152  public:
153  typedef C Collection;
154  typedef boost::sub_range<const Collection> const_range;
155  typedef boost::sub_range<Collection> range;
156 
158 
160  template <typename RefKey>
161  const_range operator[](const RefKey &r) const {
162  return get(r.id(), r.key());
163  }
164  // ---- and the non-const sister
166  template <typename RefKey>
167  range operator[](const RefKey &r) {
168  return get(r.id(), r.key());
169  }
170 
172  template <typename RefKey>
173  Collection getValues(const RefKey &r) const {
174  return getValues(r.id(), r.key());
175  }
176 
178  bool contains(const edm::ProductID &id) const { return indices_.contains(id); }
179 
181  const_range get(const edm::ProductID &id, unsigned int t) const;
182  // ---- and the non-const sister
184  range get(const edm::ProductID &id, unsigned int t);
185 
187  Collection getValues(const edm::ProductID &id, unsigned int t) const;
188 
190  indices_.swap(other.indices_);
191  data_.swap(other.data_);
192  }
193 
195  unsigned int dataSize() const { return data_.size(); }
196 
198  unsigned int size() const { return indices_.size(); }
199 
201  bool empty() const { return indices_.empty(); }
202 
207  class FastFiller {
208  public:
209  template <typename HandleType>
212 
215 
217 
219  template <typename KeyRef>
220  void setValues(const KeyRef &k, const Collection &refs) {
221  setValues(k.id(), k.key(), refs);
222  }
223 
225  void setValues(const edm::ProductID &id, unsigned int key, const Collection &refs);
226 
227  private:
230  std::shared_ptr<IndexFiller> indexFiller_;
231 
232  }; // FastFiller
233  friend class FastFiller;
234 
235  template <typename HandleType>
236  FastFiller fastFiller(const HandleType &handle) {
237  return FastFiller(*this, handle);
238  }
239 
245  class LazyFiller {
246  public:
247  template <typename HandleType>
248  LazyFiller(MultiAssociation &assoc, const HandleType &handle, bool fillOnExit = false)
249  : assoc_(assoc),
250  id_(handle.id()),
251  size_(handle->size()),
252  tempValues_(new TempValues()),
253  fillOnExit_(fillOnExit) {}
254  ~LazyFiller() noexcept(false) {
255  if (fillOnExit_)
256  fill();
257  }
258 
263  void fill() noexcept(false);
264 
266  void setFillOnExit(bool fillOnExit) { fillOnExit_ = fillOnExit; }
267 
269  template <typename KeyRef>
270  void setValues(const KeyRef &k, const Collection &refs);
271 
274  template <typename KeyRef>
275  void swapValues(const KeyRef &k, Collection &refs);
276 
277  private:
278  typedef std::map<unsigned int, Collection> TempValues;
281  unsigned int size_;
282  std::shared_ptr<TempValues> tempValues_;
284  }; // LazyFiller
285  friend class LazyFiller;
286 
287  template <typename HandleType>
288  LazyFiller lazyFiller(const HandleType &h, bool fillOnExit = false) {
289  return LazyFiller(*this, h, fillOnExit);
290  }
291 
292  //Used by ROOT storage
294 
295  private:
296  typedef helper::IndexRangeAssociation Indices;
299 
300  }; // class
301 
302  // Free swap function
303  template <typename C>
304  inline void swap(MultiAssociation<C> &lhs, MultiAssociation<C> &rhs) {
305  lhs.swap(rhs);
306  }
307 
308  //============= IMPLEMENTATION OF THE METHODS =============
309  template <typename C>
311  Indices::range idxrange = indices_.get(id, key);
312  return const_range(data_.begin() + idxrange.first, data_.begin() + idxrange.second);
313  }
314 
315  template <typename C>
317  Indices::range idxrange = indices_.get(id, key);
318  return range(data_.begin() + idxrange.first, data_.begin() + idxrange.second);
319  }
320 
321  template <typename C>
323  unsigned int key) const {
324  Collection ret;
325  const_range values = get(id, key);
326  for (typename const_range::const_iterator it = values.begin(), ed = values.end(); it != ed; ++it) {
327  ret.push_back(*it);
328  }
329  return ret;
330  }
331 
332  template <typename C>
333  void MultiAssociation<C>::FastFiller::setValues(const edm::ProductID &id, unsigned int key, const Collection &vals) {
334  indexFiller_->insert(id, key, assoc_.data_.size(), vals.size());
335  for (typename Collection::const_iterator it = vals.begin(), ed = vals.end(); it != ed; ++it) {
336  assoc_.data_.push_back(*it);
337  }
338  }
339 
340  template <typename C>
341  template <typename KeyRef>
342  void MultiAssociation<C>::LazyFiller::setValues(const KeyRef &k, const Collection &vals) {
343  if (k.id() != id_)
344  Indices::throwUnexpectedProductID(k.id(), id_, "LazyFiller::insert");
345  (*tempValues_)[k.key()] = vals;
346  }
347 
348  template <typename C>
349  template <typename KeyRef>
351  if (k.id() != id_)
352  Indices::throwUnexpectedProductID(k.id(), id_, "LazyFiller::insert");
353  vals.swap((*tempValues_)[k.key()]);
354  }
355 
356  template <typename C>
358  if (id_ != ProductID()) { // protection against double filling
359  typename MultiAssociation<C>::FastFiller filler(assoc_, id_, size_);
360  for (typename TempValues::const_iterator it = tempValues_->begin(), ed = tempValues_->end(); it != ed; ++it) {
361  filler.setValues(id_, it->first, it->second);
362  }
363  id_ = ProductID(); // protection against double filling
364  }
365  }
366 
367 } // namespace edm
368 
369 #endif
runTheMatrix.ret
ret
prodAgent to be discontinued
Definition: runTheMatrix.py:355
edm::helper::IndexRangeAssociation::range
std::pair< unsigned int, unsigned int > range
Definition: MultiAssociation.h:74
edm::helper::swap
void swap(IndexRangeAssociation &lhs, IndexRangeAssociation &rhs)
Definition: MultiAssociation.h:146
edm::helper::IndexRangeAssociation::IDComparator
Definition: MultiAssociation.h:140
edm::MultiAssociation::FastFiller
friend class FastFiller
Definition: MultiAssociation.h:233
edm::helper::IndexRangeAssociation
Definition: MultiAssociation.h:72
edm::helper::IndexRangeAssociation::FastFiller::start_
unsigned int start_
Definition: MultiAssociation.h:122
funct::false
false
Definition: Factorize.h:34
edm::MultiAssociation::LazyFiller::~LazyFiller
~LazyFiller() noexcept(false)
Definition: MultiAssociation.h:254
edm::MultiAssociation::getValues
Collection getValues(const RefKey &r) const
Get a copy of the values for this key (slow!)
Definition: MultiAssociation.h:173
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:124
edm::helper::IndexRangeAssociation::FastFiller::id_
const ProductID id_
Definition: MultiAssociation.h:121
patZpeak.handle
handle
Definition: patZpeak.py:23
edm::MultiAssociation::LazyFiller::swapValues
void swapValues(const KeyRef &k, Collection &refs)
Definition: MultiAssociation.h:350
edm::helper::IndexRangeAssociation::id_off_pair
std::pair< edm::ProductID, unsigned int > id_off_pair
Definition: MultiAssociation.h:133
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:288
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:248
edm::MultiAssociation::LazyFiller::id_
ProductID id_
Definition: MultiAssociation.h:280
edm::MultiAssociation::dataSize
unsigned int dataSize() const
Returns the number of values.
Definition: MultiAssociation.h:195
edm::helper::IndexRangeAssociation::id_offsets_
id_offset_vector id_offsets_
Definition: MultiAssociation.h:136
newFWLiteAna.found
found
Definition: newFWLiteAna.py:118
edm::MultiAssociation::range
boost::sub_range< Collection > range
Definition: MultiAssociation.h:155
edm::MultiAssociation::LazyFiller
Definition: MultiAssociation.h:245
trackingPlots.assoc
assoc
Definition: trackingPlots.py:183
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:112
edm::helper::IndexRangeAssociation::throwUnexpectedProductID
static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where)
Definition: MultiAssociation.cc:119
edm::MultiAssociation::FastFiller
Definition: MultiAssociation.h:207
edm::MultiAssociation::LazyFiller::fillOnExit_
bool fillOnExit_
Definition: MultiAssociation.h:283
edm::helper::IndexRangeAssociation::id_offset_vector
std::vector< id_off_pair > id_offset_vector
Definition: MultiAssociation.h:134
edm::helper::IndexRangeAssociation::empty
bool empty() const
True if it's empty (no keys)
Definition: MultiAssociation.h:96
contentValuesCheck.values
values
Definition: contentValuesCheck.py:38
edm::MultiAssociation::Collection
C Collection
Definition: MultiAssociation.h:153
edm::helper::IndexRangeAssociation::FastFiller::end_
unsigned int end_
Definition: MultiAssociation.h:122
edm::MultiAssociation::FastFiller::~FastFiller
~FastFiller()
Definition: MultiAssociation.h:216
ProductID.h
edm::MultiAssociation
Definition: MultiAssociation.h:151
edm::MultiAssociation::LazyFiller::TempValues
std::map< unsigned int, Collection > TempValues
Definition: MultiAssociation.h:278
edm::helper::IndexRangeAssociation::FastFiller::FastFiller
FastFiller(IndexRangeAssociation &assoc, ProductID id, unsigned int size)
Make a filler for a collection with a given product id and size.
Definition: MultiAssociation.cc:42
trackingPlots.other
other
Definition: trackingPlots.py:1465
CMS_CLASS_VERSION
#define CMS_CLASS_VERSION(_version_)
Definition: CMS_CLASS_VERSION.h:30
edm::helper::IndexRangeAssociation::IndexRangeAssociation
IndexRangeAssociation()
Definition: MultiAssociation.h:76
edm::helper::IndexRangeAssociation::size
unsigned int size() const
Size of this collection (number of keys)
Definition: MultiAssociation.h:93
h
dqmdumpme.k
k
Definition: dqmdumpme.py:60
OrderedSet.t
t
Definition: OrderedSet.py:90
edm::helper::IndexRangeAssociation::offset_vector
std::vector< int > offset_vector
Definition: MultiAssociation.h:135
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:342
edm::MultiAssociation::size
unsigned int size() const
Returns the number of keys.
Definition: MultiAssociation.h:198
edm::MultiAssociation::LazyFiller::size_
unsigned int size_
Definition: MultiAssociation.h:281
edm::MultiAssociation::FastFiller::FastFiller
FastFiller(MultiAssociation &assoc, const HandleType &handle)
Definition: MultiAssociation.h:210
trigObjTnPSource_cfi.filler
filler
Definition: trigObjTnPSource_cfi.py:21
edm::MultiAssociation::fastFiller
FastFiller fastFiller(const HandleType &handle)
Definition: MultiAssociation.h:236
helper
Definition: helper.py:1
edm::helper::IndexRangeAssociation::ref_offsets_
offset_vector ref_offsets_
Definition: MultiAssociation.h:137
edm::MultiAssociation::FastFiller::assoc_
MultiAssociation & assoc_
Definition: MultiAssociation.h:228
edm::MultiAssociation::FastFiller::FastFiller
FastFiller(MultiAssociation &assoc, edm::ProductID id, unsigned int size)
Definition: MultiAssociation.h:213
svgfig.template
def template(fileName, svg, replaceme="REPLACEME")
Definition: svgfig.py:521
edm::MultiAssociation::LazyFiller::tempValues_
std::shared_ptr< TempValues > tempValues_
Definition: MultiAssociation.h:282
alignCSCRings.r
r
Definition: alignCSCRings.py:93
edm::helper::IndexRangeAssociation::operator[]
range operator[](const RefKey &r) const
Definition: MultiAssociation.h:81
edm::helper::IndexRangeAssociation::IDComparator::operator()
bool operator()(const id_off_pair &p, const edm::ProductID &id) const
Definition: MultiAssociation.h:141
edm::MultiAssociation::indices_
Indices indices_
Definition: MultiAssociation.h:297
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:220
gen::C
C
Definition: PomwigHadronizer.cc:76
edm::MultiAssociation::LazyFiller::fill
void fill() noexcept(false)
Definition: MultiAssociation.h:357
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:266
triggerObjects_cff.id
id
Definition: triggerObjects_cff.py:31
edm::MultiAssociation::FastFiller::IndexFiller
edm::helper::IndexRangeAssociation::FastFiller IndexFiller
Definition: MultiAssociation.h:229
edm::MultiAssociation::MultiAssociation
MultiAssociation()
Definition: MultiAssociation.h:157
edm::MultiAssociation::contains
bool contains(const edm::ProductID &id) const
True if there are keys from this product id.
Definition: MultiAssociation.h:178
edm::MultiAssociation::FastFiller::indexFiller_
std::shared_ptr< IndexFiller > indexFiller_
Definition: MultiAssociation.h:230
edm::MultiAssociation::data_
Collection data_
Definition: MultiAssociation.h:298
edm::helper::IndexRangeAssociation::FastFiller::assoc_
IndexRangeAssociation & assoc_
Definition: MultiAssociation.h:120
edm::MultiAssociation::operator[]
const_range operator[](const RefKey &r) const
Get a range of values for this key (fast)
Definition: MultiAssociation.h:161
edm::MultiAssociation::LazyFiller
friend class LazyFiller
Definition: MultiAssociation.h:285
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:310
edm::helper::IndexRangeAssociation::isFilling_
bool isFilling_
Definition: MultiAssociation.h:139
edm::helper::IndexRangeAssociation::FastFiller
Definition: MultiAssociation.h:102
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:279
edm::ProductID
Definition: ProductID.h:27
edm::MultiAssociation::swap
void swap(MultiAssociation &other)
Definition: MultiAssociation.h:189
edm::MultiAssociation::const_range
boost::sub_range< const Collection > const_range
Definition: MultiAssociation.h:154
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:201
edm::MultiAssociation::operator[]
range operator[](const RefKey &r)
Get a range of values for this key (fast)
Definition: MultiAssociation.h:167