File indexing completed on 2024-04-06 12:03:50
0001 #ifndef DataFormats_Common_AssociationMap_h
0002 #define DataFormats_Common_AssociationMap_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0034 #include "DataFormats/Common/interface/RefVector.h"
0035 #include "DataFormats/Common/interface/OneToValue.h"
0036 #include "DataFormats/Common/interface/OneToOne.h"
0037 #include "DataFormats/Common/interface/OneToMany.h"
0038 #include "DataFormats/Common/interface/OneToManyWithQuality.h"
0039
0040 #include <utility>
0041 #include "oneapi/tbb/concurrent_unordered_map.h"
0042
0043 namespace edm {
0044
0045 class EDProductGetter;
0046
0047 template <typename Tag>
0048 class AssociationMap {
0049
0050
0051 typedef typename Tag::val_type internal_val_type;
0052
0053 public:
0054
0055 typedef AssociationMap<Tag> self;
0056
0057 typedef Tag tag_type;
0058
0059 typedef typename Tag::index_type index_type;
0060
0061 typedef typename Tag::key_type key_type;
0062
0063 typedef typename Tag::data_type data_type;
0064
0065 typedef typename Tag::ref_type ref_type;
0066
0067 typedef typename Tag::map_type map_type;
0068
0069 typedef typename map_type::size_type size_type;
0070
0071 typedef helpers::KeyVal<key_type, internal_val_type> value_type;
0072
0073 typedef typename value_type::value_type result_type;
0074
0075 typedef typename oneapi::tbb::concurrent_unordered_map<index_type, value_type> internal_transient_map_type;
0076
0077
0078 struct const_iterator {
0079 typedef typename self::value_type value_type;
0080 typedef ptrdiff_t difference_type;
0081 typedef value_type* pointer;
0082 typedef value_type& reference;
0083 typedef typename map_type::const_iterator::iterator_category iterator_category;
0084 const_iterator() : map_(nullptr) {}
0085 const_iterator(const self* map, typename map_type::const_iterator mi) : map_(map), i(mi) {}
0086 const_iterator& operator++() {
0087 ++i;
0088 return *this;
0089 }
0090 const_iterator operator++(int) {
0091 const_iterator ci = *this;
0092 ++i;
0093 return ci;
0094 }
0095 const_iterator& operator--() {
0096 --i;
0097 return *this;
0098 }
0099 const_iterator operator--(int) {
0100 const_iterator ci = *this;
0101 --i;
0102 return ci;
0103 }
0104 bool operator==(const const_iterator& ci) const { return i == ci.i; }
0105 bool operator!=(const const_iterator& ci) const { return i != ci.i; }
0106 const value_type& operator*() const { return map_->get(i->first); }
0107 const value_type* operator->() const { return &operator*(); }
0108
0109 private:
0110 const self* map_;
0111 typename map_type::const_iterator i;
0112 };
0113
0114
0115 AssociationMap() {}
0116
0117
0118
0119
0120 explicit AssociationMap(EDProductGetter const* getter) : ref_(getter) {}
0121
0122
0123 explicit AssociationMap(const ref_type& ref) : ref_(ref) {}
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 template <typename... Args>
0156 AssociationMap(Args... args) : ref_(std::forward<Args>(args)...) {}
0157
0158
0159 void clear() {
0160 map_.clear();
0161 transientMap_.clear();
0162 }
0163
0164 size_type size() const { return map_.size(); }
0165
0166 bool empty() const { return map_.empty(); }
0167
0168 void insert(const key_type& k, const data_type& v) { Tag::insert(ref_, map_, k, v); }
0169 void insert(const value_type& kv) { Tag::insert(ref_, map_, kv.key, kv.val); }
0170
0171 const_iterator begin() const { return const_iterator(this, map_.begin()); }
0172
0173 const_iterator end() const { return const_iterator(this, map_.end()); }
0174
0175 const_iterator find(const key_type& k) const {
0176 if (ref_.key.id() != k.id())
0177 return end();
0178 return find(k.key());
0179 }
0180
0181 size_type erase(const key_type& k) {
0182 index_type i = k.key();
0183 transientMap_.unsafe_erase(i);
0184 return map_.erase(i);
0185 }
0186
0187 const result_type& operator[](const key_type& k) const {
0188 helpers::checkRef(ref_.key, k);
0189 return get(k.key()).val;
0190 }
0191
0192 template <typename K>
0193 const result_type& operator[](const K& k) const {
0194 helpers::checkRef(ref_.key, k);
0195 return get(k.key()).val;
0196 }
0197
0198
0199 size_type numberOfAssociations(const key_type& k) const {
0200 if (ref_.key.id() != k.id())
0201 return 0;
0202 typename map_type::const_iterator f = map_.find(k.key());
0203 if (f == map_.end())
0204 return 0;
0205 return Tag::size(f->second);
0206 }
0207
0208 template <typename K>
0209 size_type numberOfAssociations(const K& k) const {
0210 if (ref_.key.id() != k.id())
0211 return 0;
0212 typename map_type::const_iterator f = map_.find(k.key());
0213 if (f == map_.end())
0214 return 0;
0215 return Tag::size(f->second);
0216 }
0217
0218
0219 const ref_type& refProd() const { return ref_; }
0220
0221
0222
0223 typename Tag::transient_map_type map() { return Tag::transientMap(ref_, map_); }
0224
0225
0226 typename Tag::transient_key_vector keys() { return Tag::transientKeyVector(ref_, map_); }
0227
0228
0229 typename Tag::transient_val_vector values() { return Tag::transientValVector(ref_, map_); }
0230
0231 void post_insert() { Tag::sort(map_); }
0232
0233
0234
0235
0236 struct Find {
0237 using first_argument_type = const self&;
0238 using second_argument_type = size_type;
0239 using result_type = const value_type*;
0240
0241 const result_type operator()(first_argument_type c, second_argument_type i) { return &(*c.find(i)); }
0242 };
0243
0244
0245 CMS_CLASS_VERSION(10)
0246
0247 private:
0248
0249 ref_type ref_;
0250
0251 map_type map_;
0252
0253 mutable internal_transient_map_type transientMap_;
0254
0255 const_iterator find(size_type i) const {
0256 typename map_type::const_iterator f = map_.find(i);
0257 if (f == map_.end())
0258 return end();
0259 return const_iterator(this, f);
0260 }
0261
0262 const value_type& get(size_type i) const {
0263 typename internal_transient_map_type::const_iterator tf = transientMap_.find(i);
0264 if (tf == transientMap_.end()) {
0265 typename map_type::const_iterator f = map_.find(i);
0266 if (f == map_.end())
0267 Exception::throwThis(edm::errors::InvalidReference, "can't find reference in AssociationMap at position ", i);
0268 value_type v(key_type(ref_.key, i), Tag::val(ref_, f->second));
0269 std::pair<typename internal_transient_map_type::const_iterator, bool> ins =
0270 transientMap_.insert(std::make_pair(i, v));
0271 return ins.first->second;
0272 } else {
0273 return tf->second;
0274 }
0275 }
0276 friend struct const_iterator;
0277 friend struct Find;
0278 friend struct refhelper::FindTrait<self, value_type>;
0279 template <typename, typename, typename>
0280 friend class OneToValue;
0281 template <typename, typename, typename>
0282 friend class OneToOne;
0283 template <typename, typename, typename>
0284 friend class OneToMany;
0285 template <typename, typename, typename, typename>
0286 friend class OneToManyWithQuality;
0287 };
0288
0289 namespace refhelper {
0290 template <typename Tag>
0291 struct FindTrait<AssociationMap<Tag>, typename AssociationMap<Tag>::value_type> {
0292 typedef typename AssociationMap<Tag>::Find value;
0293 };
0294 }
0295
0296 }
0297 #endif