/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
DataFormats/Common/interface/AssociationMap.h
297 строк
11 KB
Matti Kortelainen
Move stored types in io_v1 namespace, reset class versions to 3
22 май 2026, 18:18
22 май 2026, 18:18
909f324
Код
Авторство
О чём код?
#ifndef DataFormats_Common_AssociationMap_h #define DataFormats_Common_AssociationMap_h /** \class edm::AssociationMap * * one-to-many or one-to-one associative map using EDM references * * \author Luca Lista, INFN * * In general, this class is intuitive, but two special cases * deserves some extra discussion. These are somewhat unusual * corner cases, but sometimes actually have arisen. * * First, one can initialize the AssociationMap by passing in * a Handle to a collection as an argument to the constructor. * Usually it is a good way to initialize it. But this will * fail in the case where a collection template parameter to * Tag (either CKey or CVal) is a View and the underlying collection * read into the View is a RefVector, PtrVector, or vector(Ptr). * AssociationMap will behave improperly if the constructor is passed * a Handle<View<C> >. In this case, one should initialize with * a EDProductGetter const* or construct a RefToBaseProd whose * ProductID is associated with the underlying container, not * the RefVector, PtrVector, or vector<Ptr>. * * AssociationMap is designed to support cases where all the Key * Ref's point into one container and all the Val Ref's point into * one other container. For example, if one read a vector<Ptr> into * a View and the Ptr's pointed into different containers * and you tried to use these as elements of CVal, then * AssociationMap will not work. */ #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h" #include "DataFormats/Common/interface/RefVector.h" #include "DataFormats/Common/interface/OneToValue.h" #include "DataFormats/Common/interface/OneToOne.h" #include "DataFormats/Common/interface/OneToMany.h" #include "DataFormats/Common/interface/OneToManyWithQuality.h" #include <utility> #include "oneapi/tbb/concurrent_unordered_map.h" namespace edm { class EDProductGetter; template <typename Tag> class AssociationMap { /// This is the second part of the value part of /// the items stored in the transient map typedef typename Tag::val_type internal_val_type; public: /// self type typedef AssociationMap<Tag> self; /// tag/association type typedef Tag tag_type; /// index type typedef typename Tag::index_type index_type; /// insert key type typedef typename Tag::key_type key_type; /// insert data type typedef typename Tag::data_type data_type; /// Holds the RefProd or RefToBaseProd of 1 or 2 collections typedef typename Tag::ref_type ref_type; /// map type typedef typename Tag::map_type map_type; /// size type typedef typename map_type::size_type size_type; /// type returned by dereferenced iterator, also can be inserted typedef helpers::KeyVal<key_type, internal_val_type> value_type; /// type return by operator[] typedef typename value_type::value_type result_type; /// transient map type typedef typename oneapi::tbb::concurrent_unordered_map<index_type, value_type> internal_transient_map_type; /// const iterator struct const_iterator { typedef typename self::value_type value_type; typedef ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; typedef typename map_type::const_iterator::iterator_category iterator_category; const_iterator() : map_(nullptr) {} const_iterator(const self* map, typename map_type::const_iterator mi) : map_(map), i(mi) {} const_iterator& operator++() { ++i; return *this; } const_iterator operator++(int) { const_iterator ci = *this; ++i; return ci; } const_iterator& operator--() { --i; return *this; } const_iterator operator--(int) { const_iterator ci = *this; --i; return ci; } bool operator==(const const_iterator& ci) const { return i == ci.i; } bool operator!=(const const_iterator& ci) const { return i != ci.i; } const value_type& operator*() const { return map_->get(i->first); } const value_type* operator->() const { return &operator*(); } private: const self* map_; typename map_type::const_iterator i; }; /// default constructor AssociationMap() {} // You will see better performance if you use other constructors. // Use this when the arguments the other constructors require are // not easily available. explicit AssociationMap(EDProductGetter const* getter) : ref_(getter) {} // It is rare for this to be useful explicit AssociationMap(const ref_type& ref) : ref_(ref) {} // In most cases this is the best constructor to use. // This constructor should be passed 2 arguments, except in the // case where the template parameter is OneToValue where it should // be passed 1 argument. In most cases, the arguments will be valid // Handle's to the containers. Internally, the AssociationMap holds // a RefProd for each container. An argument passed here is forwarded // to a RefProd constructor. Alternatively, you can pass in // a RefProd or anything else a RefProd can be constructed from. // The exceptional case is when the container template argument // is a View (For your peace of mind, I suggest you stop reading // this comment here if you are not dealing with the View case). // Usually one would not pass a Handle argument in the View // case. Then internally AssociationMap holds a RefToBaseProd // for each container instead of a RefProd and one would pass a // RefToBaseProd as an argument in that case. Also see the comments // at the top of this file that are relevant to the View case. // In the View case, the code would sometimes look similar to // the following: // // typedef edm::AssociationMap<edm::OneToOne<edm::View<X>, edm::View<Y> > > AssocOneToOneView; // edm::Handle<edm::View<X> > inputView1; // event.getByToken(inputToken1V_, inputView1); // edm::Handle<edm::View<Y> > inputView2; // event.getByToken(inputToken2V_, inputView2); // // If you are certain the Views are not empty! // std::unique_ptr<AssocOneToOneView> assoc8(new AssocOneToOneView( // edm::makeRefToBaseProdFrom(inputView1->refAt(0), event), // edm::makeRefToBaseProdFrom(inputView2->refAt(0), event) // )); template <typename... Args> AssociationMap(Args... args) : ref_(std::forward<Args>(args)...) {} /// clear map void clear() { map_.clear(); transientMap_.clear(); } /// map size size_type size() const { return map_.size(); } /// return true if empty bool empty() const { return map_.empty(); } /// insert an association void insert(const key_type& k, const data_type& v) { Tag::insert(ref_, map_, k, v); } void insert(const value_type& kv) { Tag::insert(ref_, map_, kv.key, kv.val); } /// first iterator over the map (read only) const_iterator begin() const { return const_iterator(this, map_.begin()); } /// last iterator over the map (read only) const_iterator end() const { return const_iterator(this, map_.end()); } /// find element with specified reference key const_iterator find(const key_type& k) const { if (ref_.key.id() != k.id()) return end(); return find(k.key()); } /// erase the element whose key is k size_type erase(const key_type& k) { index_type i = k.key(); transientMap_.unsafe_erase(i); return map_.erase(i); } /// find element with specified reference key const result_type& operator[](const key_type& k) const { helpers::checkRef(ref_.key, k); return get(k.key()).val; } template <typename K> const result_type& operator[](const K& k) const { helpers::checkRef(ref_.key, k); return get(k.key()).val; } /// number of associations to a key size_type numberOfAssociations(const key_type& k) const { if (ref_.key.id() != k.id()) return 0; typename map_type::const_iterator f = map_.find(k.key()); if (f == map_.end()) return 0; return Tag::size(f->second); } template <typename K> size_type numberOfAssociations(const K& k) const { if (ref_.key.id() != k.id()) return 0; typename map_type::const_iterator f = map_.find(k.key()); if (f == map_.end()) return 0; return Tag::size(f->second); } /// return ref-prod structure const ref_type& refProd() const { return ref_; } /// fill and return a transient map /// required for ROOT interactive usage typename Tag::transient_map_type map() { return Tag::transientMap(ref_, map_); } /// fill and return a transient key vector /// required for ROOT interactive usage typename Tag::transient_key_vector keys() { return Tag::transientKeyVector(ref_, map_); } /// fill and return a transient key vector /// required for ROOT interactive usage typename Tag::transient_val_vector values() { return Tag::transientValVector(ref_, map_); } /// post insert action void post_insert() { Tag::sort(map_); } // Find should be private! However, generated reflex dictionaries do not compile // if Find is private. /// find helper struct Find { using first_argument_type = const self&; using second_argument_type = size_type; using result_type = const value_type*; const result_type operator()(first_argument_type c, second_argument_type i) { return &(*c.find(i)); } }; //Used by ROOT storage CMS_CLASS_VERSION(3) private: /// reference set ref_type ref_; /// index map map_type map_; /// transient reference map mutable internal_transient_map_type transientMap_; /// find element with index i const_iterator find(size_type i) const { typename map_type::const_iterator f = map_.find(i); if (f == map_.end()) return end(); return const_iterator(this, f); } /// return value_typeelement with key i const value_type& get(size_type i) const { typename internal_transient_map_type::const_iterator tf = transientMap_.find(i); if (tf == transientMap_.end()) { typename map_type::const_iterator f = map_.find(i); if (f == map_.end()) Exception::throwThis(edm::errors::InvalidReference, "can't find reference in AssociationMap at position ", i); value_type v(key_type(ref_.key, i), Tag::val(ref_, f->second)); std::pair<typename internal_transient_map_type::const_iterator, bool> ins = transientMap_.insert(std::make_pair(i, v)); return ins.first->second; } else { return tf->second; } } friend struct const_iterator; friend struct Find; friend struct refhelper::FindTrait<self, value_type>; template <typename, typename, typename> friend class OneToValue; template <typename, typename, typename> friend class OneToOne; template <typename, typename, typename> friend class OneToMany; template <typename, typename, typename, typename> friend class OneToManyWithQuality; }; namespace refhelper { template <typename Tag> struct FindTrait<AssociationMap<Tag>, typename AssociationMap<Tag>::value_type> { typedef typename AssociationMap<Tag>::Find value; }; } // namespace refhelper } // namespace edm #endif