CMS 3D CMS Logo

AssociationVector.h
Go to the documentation of this file.
1 #ifndef DataFormats_Common_AssociationVector_h
2 #define DataFormats_Common_AssociationVector_h
3 /* class edm::AssociationVector<CKey, CVal>
4  *
5  * adds to a std::vector<CVal> a edm::RefProd<CKey>, in such a way
6  * that, assuming that the CVal and CKey collections have the same
7  * size and are properly ordered, the two collections can be
8  * in one-to-one correspondance
9  *
10  * \author Luca Lista, INFN
11  *
12  */
13 
24 
25 #include <atomic>
26 #include <type_traits>
27 #include <memory>
28 
29 namespace edm {
30  template <class T>
31  class Ptr;
32 
33  namespace helper {
34 
36  template <typename T>
37  static T const& get(T const& t, ProductID) {
38  return t;
39  }
40  };
41 
42  template <typename T>
45  };
46 
47  template <typename REFPROD>
49 
50  template <typename C>
53  };
54 
55  template <typename T>
58  };
59  } // namespace helper
60 
61  template <typename KeyRefProd,
62  typename CVal,
63  typename KeyRef = typename helper::RefFromRefProdTrait<KeyRefProd>::ref_type,
64  typename SizeType =
65  unsigned int, //the type used here can not change when go from 32bit to 64bit or across platforms
66  typename KeyReferenceHelper = typename helper::AssociationKeyReferenceTrait<KeyRef>::type>
69  "Can not convert container size_type to unsigned int.");
71 
72  public:
73  typedef KeyRefProd refprod_type;
74  typedef typename KeyRefProd::product_type CKey;
75  typedef SizeType size_type;
76  typedef typename KeyRef::value_type key_type;
77  typedef typename std::pair<KeyRef, typename CVal::value_type> value_type;
78  typedef std::vector<value_type> transient_vector_type;
79  typedef value_type const& const_reference;
81  AssociationVector(KeyRefProd const& ref, CKey const* = nullptr);
84 
85  size_type size() const;
86  bool empty() const;
88  typename CVal::const_reference operator[](KeyRef const& k) const;
89  typename CVal::reference operator[](KeyRef const& k);
90 
91  template <typename K>
92  typename CVal::const_reference operator[](edm::Ptr<K> const& k) const;
93  template <typename K>
94  typename CVal::const_reference operator[](edm::RefToBase<K> const& k) const;
95 
96  self& operator=(self const&);
97 
98  void clear();
99  void swap(self& other);
100  KeyRefProd const& keyProduct() const { return ref_; }
101  KeyRef key(size_type i) const { return KeyRef(ref_, i); }
102  typename CVal::value_type const value(size_type i) const { return data_[i]; }
103  void setValue(size_type i, typename CVal::value_type const& val);
104  void fillView(ProductID const& id, std::vector<void const*>& pointers, FillViewHelperVector& helpers) const;
105 
106  typedef typename transient_vector_type::const_iterator const_iterator;
107 
108  const_iterator begin() const { return transientVector().begin(); }
109  const_iterator end() const { return transientVector().end(); }
110 
111  //Used by ROOT storage
113 
114  private:
116  CVal data_;
117  KeyRefProd ref_;
118  mutable std::atomic<transient_vector_type*> transientVector_;
119 
120  transient_vector_type const& transientVector() const;
121  void fixup() const;
122  };
123 
124  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
125  inline
128  fixup();
129  return *(transientVector_.load(std::memory_order_acquire));
130  }
131 
132  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
134  : data_(), ref_(), transientVector_(nullptr) {}
135 
136  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
138  KeyRefProd const& ref, CKey const* coll)
139  : data_(coll == nullptr ? ref->size() : coll->size()),
140  ref_(ref),
141  transientVector_(new transient_vector_type(coll == nullptr ? ref->size() : coll->size())) {}
142 
143  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
146  : data_(o.data_), ref_(o.ref_), transientVector_() {
147  auto t = o.transientVector_.load(std::memory_order_acquire);
148  if (t) {
149  transientVector_.store(new transient_vector_type(*t), std::memory_order_release);
150  }
151  }
152 
153  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
155  delete transientVector_.load(std::memory_order_acquire);
156  }
157 
158  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
161  return transientVector()[n];
162  }
163 
164  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
165  inline typename CVal::const_reference
167  KeyRef keyRef = KeyReferenceHelper::get(k, ref_.id());
168  checkForWrongProduct(keyRef.id(), ref_.id());
169  return data_[keyRef.key()];
170  }
171 
172  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
173  template <typename K>
174  inline typename CVal::const_reference
177  "edm::Ptr's key type is not a base class of AssociationVector's item type");
178  checkForWrongProduct(k.id(), ref_.id());
179  return data_[k.key()];
180  }
181 
182  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
183  template <typename K>
185  edm::RefToBase<K> const& k) const {
187  "edm::RefToBase's key type is not a base class of AssociationVector's item type");
188  checkForWrongProduct(k.id(), ref_.id());
189  return data_[k.key()];
190  }
191 
192  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
194  KeyRef const& k) {
195  KeyRef keyRef = KeyReferenceHelper::get(k, ref_.id());
196  auto t = transientVector_.exchange(nullptr, std::memory_order_acq_rel);
197  delete t;
198  checkForWrongProduct(keyRef.id(), ref_.id());
199  return data_[keyRef.key()];
200  }
201 
202  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
205  if (this == &o) {
206  return *this;
207  }
208  data_ = o.data_;
209  ref_ = o.ref_;
210  auto t = transientVector_.exchange(nullptr, std::memory_order_acq_rel);
211  delete t;
212  return *this;
213  }
214 
215  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
217  size_type i, typename CVal::value_type const& val) {
218  data_[i] = val;
219  KeyRef ref(ref_, i);
220  auto t = transientVector_.load(std::memory_order_acquire);
221  (*t)[i].first = ref;
222  (*t)[i].second = data_[i];
223  }
224 
225  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
228  return data_.size();
229  }
230 
231  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
233  return data_.empty();
234  }
235 
236  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
238  data_.clear();
239  auto t = transientVector_.load(std::memory_order_acquire);
240  if (t)
241  t->clear();
242  ref_ = KeyRefProd();
243  }
244 
245  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
247  data_.swap(other.data_);
248  other.transientVector_.store(
249  transientVector_.exchange(other.transientVector_.load(std::memory_order_acquire), std::memory_order_acq_rel),
250  std::memory_order_release);
251  ref_.swap(other.ref_);
252  }
253 
254  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
256  if (nullptr == transientVector_.load(std::memory_order_acquire)) {
257  std::unique_ptr<transient_vector_type> newT{new transient_vector_type(size())};
258  for (size_type i = 0; i != size(); ++i) {
259  (*newT)[i] = std::make_pair(KeyRef(ref_, i), data_[i]);
260  }
261  transient_vector_type* expected = nullptr;
262  if (transientVector_.compare_exchange_strong(expected, newT.get())) {
263  newT.release();
264  }
265  }
266  }
267 
268  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
270  ProductID const& id, std::vector<void const*>& pointers, FillViewHelperVector& helpers) const {
271  detail::reallyFillView(*this, id, pointers, helpers);
272  // pointers.reserve(this->size());
273  // for(typename CVal::const_iterator i=data_.begin(), e=data_.end(); i!=e; ++i)
274  // pointers.push_back(&(*i));
275  // // helpers is not yet filled in.
276  // //Exception::throwThis(errors::UnimplementedFeature, "AssociationVector<T>::fillView(...)");
277  }
278 
279  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
282  a.swap(b);
283  }
284 
285  //----------------------------------------------------------------------
286  //
287  // Free function template to support creation of Views.
288 
289  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
291  ProductID const& id,
292  std::vector<void const*>& pointers,
294  obj.fillView(id, pointers, helpers);
295  }
296 
297  template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
298  struct has_fillView<AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> > {
299  static bool const value = true;
300  };
301 
302 } // namespace edm
303 
304 #endif
KeyRef key(size_type i) const
void checkForWrongProduct(ProductID const &keyID, ProductID const &refID)
void fillView(AssociationVector< KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper > const &obj, ProductID const &id, std::vector< void const *> &pointers, FillViewHelperVector &helpers)
Definition: helper.py:1
size_type size() const
transient_vector_type::const_iterator const_iterator
transient_vector_type const & transientVector() const
Ref< typename RefProd< C >::product_type > ref_type
const_reference operator[](size_type n) const
self & operator=(self const &)
const_iterator begin() const
std::vector< value_type > transient_vector_type
#define CMS_CLASS_VERSION(_version_)
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:112
AssociationIdenticalKeyReference type
value_type const & const_reference
void fillView(ProductID const &id, std::vector< void const *> &pointers, FillViewHelperVector &helpers) const
std::pair< KeyRef, typename CVal::value_type > value_type
void swap(self &other)
enum
Upsilon = 1,.
Definition: value.py:1
KeyRefProd::product_type CKey
Container::transient_vector_type transient_vector_type
const_iterator end() const
KeyRefProd const & keyProduct() const
double b
Definition: hdecay.h:120
KeyRef::value_type key_type
HLT enums.
double a
Definition: hdecay.h:121
std::atomic< transient_vector_type * > transientVector_
#define get
CVal::value_type const value(size_type i) const
long double T
void setValue(size_type i, typename CVal::value_type const &val)
void reallyFillView(COLLECTION const &coll, ProductID const &id, std::vector< void const *> &ptrs, FillViewHelperVector &helpers)
Definition: FillView.h:25
std::vector< std::pair< edm::ProductID, unsigned long > > FillViewHelperVector