Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:51

0001 #ifndef DataFormats_Common_DetSetVectorNew_h
0002 #define DataFormats_Common_DetSetVectorNew_h
0003 
0004 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0005 #include "DataFormats/Common/interface/DetSetNew.h"
0006 #include "DataFormats/Common/interface/traits.h"
0007 
0008 #include <boost/iterator/transform_iterator.hpp>
0009 #include "FWCore/Utilities/interface/Exception.h"
0010 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0011 
0012 #include <atomic>
0013 #include <memory>
0014 #include <vector>
0015 #include <cassert>
0016 
0017 #include <algorithm>
0018 #include <functional>
0019 #include <iterator>
0020 #include <utility>
0021 
0022 class TestDetSet;
0023 
0024 namespace edm {
0025   namespace refhelper {
0026     template <typename T>
0027     struct FindForNewDetSetVector;
0028   }
0029 }  // namespace edm
0030 
0031 //FIXME remove New when ready
0032 namespace edmNew {
0033   typedef uint32_t det_id_type;
0034 
0035   struct CapacityExaustedException : public cms::Exception {
0036     CapacityExaustedException() : cms::Exception("Capacity exausted in DetSetVectorNew") {}
0037   };
0038 
0039   namespace dslv {
0040     template <typename T>
0041     class LazyGetter;
0042 
0043   }
0044 
0045   /* transient component of DetSetVector
0046    * for pure conviniency of dictionary declaration
0047    */
0048   namespace dstvdetails {
0049 
0050     void errorFilling();
0051     void notSafe();
0052     void errorIdExists(det_id_type iid);
0053     void throw_range(det_id_type iid);
0054 
0055     struct DetSetVectorTrans {
0056       typedef unsigned int size_type;  // for persistency
0057       typedef unsigned int id_type;
0058 
0059       DetSetVectorTrans() : m_filling(false), m_dataSize(0) {}
0060       DetSetVectorTrans& operator=(const DetSetVectorTrans&) = delete;
0061 
0062       DetSetVectorTrans(const DetSetVectorTrans& rh)
0063           :  // can't be default because of atomics
0064             m_filling(false) {
0065         // better no one is filling...
0066         assert(rh.m_filling == false);
0067         m_getter = rh.m_getter;
0068         m_dataSize.store(rh.m_dataSize.load());
0069       }
0070 
0071       DetSetVectorTrans(DetSetVectorTrans&& rh)
0072           :  // can't be default because of atomics
0073             m_filling(false) {
0074         // better no one is filling...
0075         assert(rh.m_filling == false);
0076         m_getter = std::move(rh.m_getter);
0077         m_dataSize.store(rh.m_dataSize.exchange(m_dataSize.load()));
0078       }
0079       DetSetVectorTrans& operator=(DetSetVectorTrans&& rh) {  // can't be default because of atomics
0080         // better no one is filling...
0081         assert(m_filling == false);
0082         assert(rh.m_filling == false);
0083         m_getter = std::move(rh.m_getter);
0084         m_dataSize.store(rh.m_dataSize.exchange(m_dataSize.load()));
0085         return *this;
0086       }
0087       mutable std::atomic<bool> m_filling;
0088       std::shared_ptr<void const> m_getter;
0089       mutable std::atomic<size_type> m_dataSize;
0090 
0091       void swap(DetSetVectorTrans& rh) {
0092         // better no one is filling...
0093         assert(m_filling == false);
0094         assert(rh.m_filling == false);
0095         //  std::swap(m_filling,rh.m_filling);
0096         std::swap(m_getter, rh.m_getter);
0097         m_dataSize.store(rh.m_dataSize.exchange(m_dataSize.load()));
0098       }
0099 
0100       struct Item {
0101         Item(id_type i = 0, int io = -1, size_type is = 0) : id(i), offset(io), size(is) {}
0102 
0103         Item(Item const& rh) noexcept : id(rh.id), offset(int(rh.offset)), size(rh.size) {}
0104         Item& operator=(Item const& rh) noexcept {
0105           id = rh.id;
0106           offset = int(rh.offset);
0107           size = rh.size;
0108           return *this;
0109         }
0110         Item(Item&& rh) noexcept : id(rh.id), offset(int(rh.offset)), size(rh.size) {}
0111         Item& operator=(Item&& rh) noexcept {
0112           id = rh.id;
0113           offset = int(rh.offset);
0114           size = rh.size;
0115           return *this;
0116         }
0117 
0118         id_type id;
0119         mutable std::atomic<int> offset;
0120         bool initialize() const {
0121           int expected = -1;
0122           return offset.compare_exchange_strong(expected, -2);
0123         }
0124         CMS_THREAD_GUARD(offset) mutable size_type size;
0125 
0126         bool uninitialized() const { return (-1) == offset; }
0127         bool initializing() const { return (-2) == offset; }
0128         bool isValid() const { return offset >= 0; }
0129         bool operator<(Item const& rh) const { return id < rh.id; }
0130         operator id_type() const { return id; }
0131       };
0132 
0133       bool ready() const {
0134         bool expected = false;
0135         if (!m_filling.compare_exchange_strong(expected, true))
0136           errorFilling();
0137         return true;
0138       }
0139     };
0140 
0141     inline void throwCapacityExausted() { throw CapacityExaustedException(); }
0142   }  // namespace dstvdetails
0143 
0144   /** an optitimized container that linearized a "map of vector".
0145    *  It corresponds to a set of variable size array of T each belonging
0146    *  to a "Det" identified by an 32bit id
0147    *
0148    * FIXME interface to be finalized once use-cases fully identified
0149    *
0150    * although it is sorted internally it is strongly adviced to
0151    * fill it already sorted....
0152    *
0153    */
0154   template <typename T>
0155   class DetSetVector : private dstvdetails::DetSetVectorTrans {
0156   public:
0157     typedef dstvdetails::DetSetVectorTrans Trans;
0158     typedef Trans::Item Item;
0159     typedef unsigned int size_type;  // for persistency
0160     typedef unsigned int id_type;
0161     typedef T data_type;
0162     typedef edmNew::DetSetVector<T> self;
0163     typedef edmNew::DetSet<T> DetSet;
0164     typedef dslv::LazyGetter<T> Getter;
0165     // FIXME not sure make sense....
0166     typedef DetSet value_type;
0167     typedef id_type key_type;
0168 
0169     typedef std::vector<Item> IdContainer;
0170     typedef std::vector<data_type> DataContainer;
0171     typedef typename IdContainer::iterator IdIter;
0172     typedef typename std::vector<data_type>::iterator DataIter;
0173     typedef std::pair<IdIter, DataIter> IterPair;
0174     typedef typename IdContainer::const_iterator const_IdIter;
0175     typedef typename std::vector<data_type>::const_iterator const_DataIter;
0176     typedef std::pair<const_IdIter, const_DataIter> const_IterPair;
0177 
0178     typedef typename edm::refhelper::FindForNewDetSetVector<data_type> RefFinder;
0179 
0180     struct IterHelp {
0181       typedef DetSet result_type;
0182       //      IterHelp() : v(0),update(true){}
0183       IterHelp() : m_v(nullptr), m_update(false) {}
0184       IterHelp(DetSetVector<T> const& iv, bool iup) : m_v(&iv), m_update(iup) {}
0185 
0186       result_type operator()(Item const& item) const { return result_type(*m_v, item, m_update); }
0187 
0188     private:
0189       DetSetVector<T> const* m_v;
0190       bool m_update;
0191     };
0192 
0193     typedef boost::transform_iterator<IterHelp, const_IdIter> const_iterator;
0194     typedef std::pair<const_iterator, const_iterator> Range;
0195 
0196     /* fill the lastest inserted DetSet
0197      */
0198     class FastFiller {
0199     public:
0200       typedef typename DetSetVector<T>::data_type value_type;
0201       typedef typename DetSetVector<T>::id_type key_type;
0202       typedef typename DetSetVector<T>::id_type id_type;
0203       typedef typename DetSetVector<T>::size_type size_type;
0204 
0205       // here just to make the compiler happy
0206       static DetSetVector<T>::Item& dummy() {
0207         assert(false);
0208         static DetSetVector<T>::Item d;
0209         return d;
0210       }
0211 
0212       FastFiller(DetSetVector<T>& iv, id_type id, bool isaveEmpty = false)
0213           : m_v(iv), m_item(m_v.ready() ? m_v.push_back(id) : dummy()), m_saveEmpty(isaveEmpty) {
0214         if (m_v.onDemand())
0215           dstvdetails::notSafe();
0216       }
0217 
0218       FastFiller(DetSetVector<T>& iv, typename DetSetVector<T>::Item& it, bool isaveEmpty = false)
0219           : m_v(iv), m_item(it), m_saveEmpty(isaveEmpty) {
0220         if (m_v.onDemand())
0221           dstvdetails::notSafe();
0222         if (m_v.ready())
0223           m_item.offset = int(m_v.m_data.size());
0224       }
0225       ~FastFiller() {
0226         if (!m_saveEmpty && m_item.size == 0) {
0227           m_v.pop_back(m_item.id);
0228         }
0229         assert(m_v.m_filling == true);
0230         m_v.m_filling = false;
0231       }
0232 
0233       void abort() {
0234         m_v.pop_back(m_item.id);
0235         m_saveEmpty = true;  // avoid mess in destructor
0236       }
0237 
0238       void checkCapacityExausted() const {
0239         if (m_v.onDemand() && m_v.m_data.size() == m_v.m_data.capacity())
0240           dstvdetails::throwCapacityExausted();
0241       }
0242 
0243       void checkCapacityExausted(size_type s) const {
0244         if (m_v.onDemand() && m_v.m_data.size() + s > m_v.m_data.capacity())
0245           dstvdetails::throwCapacityExausted();
0246       }
0247 
0248       void reserve(size_type s) {
0249         if (m_item.offset + s <= m_v.m_data.capacity())
0250           return;
0251         if (m_v.onDemand())
0252           dstvdetails::throwCapacityExausted();
0253         m_v.m_data.reserve(m_item.offset + s);
0254       }
0255 
0256       void resize(size_type s) {
0257         checkCapacityExausted(s);
0258         m_v.m_data.resize(m_item.offset + s);
0259         m_v.m_dataSize = m_v.m_data.size();
0260         m_item.size = s;
0261       }
0262 
0263       id_type id() const { return m_item.id; }
0264       size_type size() const { return m_item.size; }
0265       bool empty() const { return m_item.size == 0; }
0266 
0267       data_type& operator[](size_type i) { return m_v.m_data[m_item.offset + i]; }
0268       DataIter begin() { return m_v.m_data.begin() + m_item.offset; }
0269       DataIter end() { return begin() + size(); }
0270 
0271       template <typename... Args>
0272       void emplace_back(Args&&... args) {
0273         checkCapacityExausted();
0274         m_v.m_data.emplace_back(args...);
0275         ++m_v.m_dataSize;
0276         m_item.size++;
0277       }
0278 
0279       void push_back(data_type const& d) {
0280         checkCapacityExausted();
0281         m_v.m_data.push_back(d);
0282         ++m_v.m_dataSize;
0283         m_item.size++;
0284       }
0285 
0286       void push_back(data_type&& d) {
0287         checkCapacityExausted();
0288         m_v.m_data.push_back(std::move(d));
0289         ++m_v.m_dataSize;
0290         m_item.size++;
0291       }
0292 
0293       data_type& back() { return m_v.m_data.back(); }
0294 
0295     private:
0296       //for testing
0297       friend class ::TestDetSet;
0298 
0299       DetSetVector<T>& m_v;
0300       typename DetSetVector<T>::Item& m_item;
0301       bool m_saveEmpty;
0302     };
0303 
0304     /* fill on demand a given  DetSet
0305      */
0306     class TSFastFiller {
0307     public:
0308       typedef typename DetSetVector<T>::data_type value_type;
0309       typedef typename DetSetVector<T>::id_type key_type;
0310       typedef typename DetSetVector<T>::id_type id_type;
0311       typedef typename DetSetVector<T>::size_type size_type;
0312 
0313       // here just to make the compiler happy
0314       static DetSetVector<T>::Item const& dummy() {
0315         assert(false);
0316         static DetSetVector<T>::Item const d;
0317         return d;
0318       }
0319       // this constructor is not supposed to be used in Concurrent mode
0320       TSFastFiller(DetSetVector<T>& iv, id_type id) : m_v(iv), m_item(m_v.ready() ? iv.push_back(id) : dummy()) {
0321         assert(m_v.m_filling == true);
0322         m_v.m_filling = false;
0323       }
0324 
0325       TSFastFiller(DetSetVector<T> const& iv, typename DetSetVector<T>::Item const& it) : m_v(iv), m_item(it) {}
0326       ~TSFastFiller() {
0327         bool expected = false;
0328         while (!m_v.m_filling.compare_exchange_weak(expected, true)) {
0329           expected = false;
0330           nanosleep(nullptr, nullptr);
0331         }
0332         int offset = m_v.m_data.size();
0333         if (m_v.onDemand() && full()) {
0334           m_v.m_filling = false;
0335           dstvdetails::throwCapacityExausted();
0336         }
0337         std::move(m_lv.begin(), m_lv.end(), std::back_inserter(m_v.m_data));
0338         m_item.size = m_lv.size();
0339         m_item.offset = offset;
0340 
0341         m_v.m_dataSize = m_v.m_data.size();
0342         assert(m_v.m_filling == true);
0343         m_v.m_filling = false;
0344       }
0345 
0346       bool full() const {
0347         int offset = m_v.m_dataSize;
0348         return m_v.m_data.capacity() < offset + m_lv.size();
0349       }
0350 
0351       void abort() { m_lv.clear(); }
0352 
0353       void reserve(size_type s) { m_lv.reserve(s); }
0354 
0355       void resize(size_type s) { m_lv.resize(s); }
0356 
0357       id_type id() const { return m_item.id; }
0358       size_type size() const { return m_lv.size(); }
0359       bool empty() const { return m_lv.empty(); }
0360 
0361       data_type& operator[](size_type i) { return m_lv[i]; }
0362       DataIter begin() { return m_lv.begin(); }
0363       DataIter end() { return m_lv.end(); }
0364 
0365       template <typename... Args>
0366       void emplace_back(Args&&... args) {
0367         m_lv.emplace_back(args...);
0368       }
0369 
0370       void push_back(data_type const& d) { m_lv.push_back(d); }
0371       void push_back(data_type&& d) { m_lv.push_back(std::move(d)); }
0372 
0373       data_type& back() { return m_lv.back(); }
0374 
0375     private:
0376       //for testing
0377       friend class ::TestDetSet;
0378 
0379       std::vector<T> m_lv;
0380       DetSetVector<T> const& m_v;
0381       typename DetSetVector<T>::Item const& m_item;
0382     };
0383 
0384     friend class FastFiller;
0385     friend class TSFastFiller;
0386     friend class edmNew::DetSet<T>;
0387 
0388     class FindForDetSetVector {
0389     public:
0390       using first_argument_type = const edmNew::DetSetVector<T>&;
0391       using second_argument_type = unsigned int;
0392       using result_type = const T*;
0393 
0394       result_type operator()(first_argument_type iContainer, second_argument_type iIndex) {
0395         bool expected = false;
0396         while (!iContainer.m_filling.compare_exchange_weak(expected, true, std::memory_order_acq_rel)) {
0397           expected = false;
0398           nanosleep(nullptr, nullptr);
0399         }
0400         result_type item = &(iContainer.m_data[iIndex]);
0401         assert(iContainer.m_filling == true);
0402         iContainer.m_filling = false;
0403         return item;
0404       }
0405     };
0406     friend class FindForDetSetVector;
0407 
0408     explicit DetSetVector(int isubdet = 0) : m_subdetId(isubdet) {}
0409 
0410     DetSetVector(std::shared_ptr<dslv::LazyGetter<T>> iGetter, const std::vector<det_id_type>& iDets, int isubdet = 0);
0411 
0412     ~DetSetVector() {
0413       // delete content if T is pointer...
0414     }
0415 
0416     // default or delete is the same...
0417     DetSetVector& operator=(const DetSetVector&) = delete;
0418     // Implement copy constructor because of a (possibly temporary)
0419     // need in heterogeneous framework prototyping. In general this
0420     // class is still supposed to be non-copyable, so to prevent
0421     // accidental copying the assignment operator is left deleted.
0422     DetSetVector(const DetSetVector&) = default;
0423     DetSetVector(DetSetVector&&) = default;
0424     DetSetVector& operator=(DetSetVector&&) = default;
0425 
0426     bool onDemand() const { return static_cast<bool>(m_getter); }
0427 
0428     void swap(DetSetVector& rh) {
0429       DetSetVectorTrans::swap(rh);
0430       std::swap(m_subdetId, rh.m_subdetId);
0431       std::swap(m_ids, rh.m_ids);
0432       std::swap(m_data, rh.m_data);
0433     }
0434 
0435     void swap(IdContainer& iic, DataContainer& idc) {
0436       std::swap(m_ids, iic);
0437       std::swap(m_data, idc);
0438     }
0439 
0440     void reserve(size_t isize, size_t dsize) {
0441       m_ids.reserve(isize);
0442       m_data.reserve(dsize);
0443     }
0444 
0445     void shrink_to_fit() {
0446       clean();
0447       m_ids.shrink_to_fit();
0448       m_data.shrink_to_fit();
0449     }
0450 
0451     void resize(size_t isize, size_t dsize) {
0452       m_ids.resize(isize);
0453       m_data.resize(dsize);
0454       m_dataSize = m_data.size();
0455     }
0456 
0457     void clean() {
0458       m_ids.erase(std::remove_if(m_ids.begin(), m_ids.end(), [](Item const& m) { return 0 == m.size; }), m_ids.end());
0459     }
0460 
0461     // FIXME not sure what the best way to add one cell to cont
0462     DetSet insert(id_type iid, data_type const* idata, size_type isize) {
0463       Item& item = addItem(iid, isize);
0464       m_data.resize(m_data.size() + isize);
0465       std::copy(idata, idata + isize, m_data.begin() + item.offset);
0466       m_dataSize = m_data.size();
0467       return DetSet(*this, item, false);
0468     }
0469     //make space for it
0470     DetSet insert(id_type iid, size_type isize) {
0471       Item& item = addItem(iid, isize);
0472       m_data.resize(m_data.size() + isize);
0473       m_dataSize = m_data.size();
0474       return DetSet(*this, item, false);
0475     }
0476 
0477     // to be used with a FastFiller
0478     Item& push_back(id_type iid) { return addItem(iid, 0); }
0479 
0480     // remove last entry (usually only if empty...)
0481     void pop_back(id_type iid) {
0482       const_IdIter p = findItem(iid);
0483       if (p == m_ids.end())
0484         return;  //bha!
0485       // sanity checks...  (shall we throw or assert?)
0486       if ((*p).isValid() && (*p).size > 0 && m_data.size() == (*p).offset + (*p).size) {
0487         m_data.resize((*p).offset);
0488         m_dataSize = m_data.size();
0489       }
0490       m_ids.erase(m_ids.begin() + (p - m_ids.begin()));
0491     }
0492 
0493   private:
0494     Item& addItem(id_type iid, size_type isize) {
0495       Item it(iid, size_type(m_data.size()), isize);
0496       IdIter p = std::lower_bound(m_ids.begin(), m_ids.end(), it);
0497       if (p != m_ids.end() && !(it < *p))
0498         dstvdetails::errorIdExists(iid);
0499       return *m_ids.insert(p, std::move(it));
0500     }
0501 
0502   public:
0503     //---------------------------------------------------------
0504 
0505     bool exists(id_type i) const { return findItem(i) != m_ids.end(); }
0506 
0507     bool isValid(id_type i) const {
0508       const_IdIter p = findItem(i);
0509       return p != m_ids.end() && (*p).isValid();
0510     }
0511 
0512     /*
0513     DetSet operator[](id_type i) {
0514       const_IdIter p = findItem(i);
0515       if (p==m_ids.end()) what???
0516       return DetSet(*this,p-m_ids.begin());
0517     }
0518     */
0519 
0520     DetSet operator[](id_type i) const {
0521       const_IdIter p = findItem(i);
0522       if (p == m_ids.end())
0523         dstvdetails::throw_range(i);
0524       return DetSet(*this, *p, true);
0525     }
0526 
0527     // slow interface
0528     //    const_iterator find(id_type i, bool update=true) const {
0529     const_iterator find(id_type i, bool update = false) const {
0530       const_IdIter p = findItem(i);
0531       return (p == m_ids.end()) ? end() : boost::make_transform_iterator(p, IterHelp(*this, update));
0532     }
0533 
0534     // slow interface
0535     const_IdIter findItem(id_type i) const {
0536       std::pair<const_IdIter, const_IdIter> p = std::equal_range(m_ids.begin(), m_ids.end(), Item(i));
0537       return (p.first != p.second) ? p.first : m_ids.end();
0538     }
0539 
0540     //    const_iterator begin(bool update=true) const {
0541     const_iterator begin(bool update = false) const {
0542       return boost::make_transform_iterator(m_ids.begin(), IterHelp(*this, update));
0543     }
0544 
0545     //    const_iterator end(bool update=true) const {
0546     const_iterator end(bool update = false) const {
0547       return boost::make_transform_iterator(m_ids.end(), IterHelp(*this, update));
0548     }
0549 
0550     // return an iterator range (implemented here to avoid dereference of detset)
0551     template <typename CMP>
0552     //    Range equal_range(id_type i, CMP cmp, bool update=true) const {
0553     Range equal_range(id_type i, CMP cmp, bool update = false) const {
0554       std::pair<const_IdIter, const_IdIter> p = std::equal_range(m_ids.begin(), m_ids.end(), i, cmp);
0555       return Range(boost::make_transform_iterator(p.first, IterHelp(*this, update)),
0556                    boost::make_transform_iterator(p.second, IterHelp(*this, update)));
0557     }
0558 
0559     int subdetId() const { return m_subdetId; }
0560 
0561     bool empty() const { return m_ids.empty(); }
0562 
0563     size_type dataSize() const { return onDemand() ? size_type(m_dataSize) : size_type(m_data.size()); }
0564 
0565     size_type size() const { return m_ids.size(); }
0566 
0567     //FIXME fast interfaces, not consistent with associative nature of container....
0568 
0569     data_type operator()(size_t cell, size_t frame) const { return m_data[m_ids[cell].offset + frame]; }
0570 
0571     data_type const* data(size_t cell) const { return &m_data[m_ids[cell].offset]; }
0572 
0573     size_type detsetSize(size_t cell) const { return m_ids[cell].size; }
0574 
0575     id_type id(size_t cell) const { return m_ids[cell].id; }
0576 
0577     Item const& item(size_t cell) const { return m_ids[cell]; }
0578 
0579     //------------------------------
0580 
0581     IdContainer const& ids() const { return m_ids; }
0582     DataContainer const& data() const { return m_data; }
0583 
0584     //Used by ROOT storage
0585     CMS_CLASS_VERSION(10)
0586 
0587   private:
0588     //for testing
0589     friend class ::TestDetSet;
0590 
0591     void update(Item const& item) const;
0592 
0593     // subdetector id (as returned by  DetId::subdetId())
0594     int m_subdetId;
0595 
0596     // Workaround for ROOT 6 bug.
0597     // ROOT6 has a problem with this IdContainer typedef
0598     //IdContainer m_ids;
0599     std::vector<Trans::Item> m_ids;
0600     CMS_THREAD_GUARD(dstvdetails::DetSetVectorTrans::m_filling) mutable DataContainer m_data;
0601   };
0602 
0603   namespace dslv {
0604     template <typename T>
0605     class LazyGetter {
0606     public:
0607       virtual ~LazyGetter() {}
0608       virtual void fill(typename DetSetVector<T>::TSFastFiller&) const = 0;
0609     };
0610   }  // namespace dslv
0611 
0612   template <typename T>
0613   inline DetSetVector<T>::DetSetVector(std::shared_ptr<Getter> iGetter,
0614                                        const std::vector<det_id_type>& iDets,
0615                                        int isubdet)
0616       : m_subdetId(isubdet) {
0617     m_getter = iGetter;
0618 
0619     m_ids.reserve(iDets.size());
0620     det_id_type sanityCheck = 0;
0621     for (std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
0622          itDetId != itDetIdEnd;
0623          ++itDetId) {
0624       assert(sanityCheck < *itDetId && "vector of det_id_type was not ordered");
0625       sanityCheck = *itDetId;
0626       m_ids.push_back(*itDetId);
0627     }
0628   }
0629 
0630   template <typename T>
0631   inline void DetSetVector<T>::update(const Item& item) const {
0632     // no m_getter or already updated
0633     if (!m_getter) {
0634       assert(item.isValid());
0635       return;
0636     }
0637     if (item.initialize()) {
0638       assert(item.initializing());
0639       {
0640         TSFastFiller ff(*this, item);
0641         static_cast<Getter const*>(m_getter.get())->fill(ff);
0642       }
0643       assert(item.isValid());
0644     }
0645   }
0646 
0647   template <typename T>
0648   inline void DetSet<T>::set(DetSetVector<T> const& icont, typename Container::Item const& item, bool update) {
0649     // if an item is being updated we wait
0650     if (update)
0651       icont.update(item);
0652     while (item.initializing())
0653       nanosleep(nullptr, nullptr);
0654     m_data = &icont.data();
0655     m_id = item.id;
0656     m_offset = item.offset;
0657     m_size = item.size;
0658   }
0659 }  // namespace edmNew
0660 
0661 #include "DataFormats/Common/interface/Ref.h"
0662 #include <type_traits>
0663 
0664 //specialize behavior of edm::Ref to get access to the 'Det'
0665 namespace edm {
0666   /* Reference to an item inside a new DetSetVector ... */
0667   namespace refhelper {
0668     template <typename T>
0669     struct FindTrait<typename edmNew::DetSetVector<T>, T> {
0670       typedef typename edmNew::DetSetVector<T>::FindForDetSetVector value;
0671     };
0672   }  // namespace refhelper
0673   /* ... as there was one for the original DetSetVector*/
0674 
0675   /* Probably this one is not that useful .... */
0676   namespace refhelper {
0677     template <typename T>
0678     struct FindSetForNewDetSetVector {
0679       using first_argument_type = const edmNew::DetSetVector<T>&;
0680       using second_argument_type = unsigned int;
0681       using result_type = edmNew::DetSet<T>;
0682 
0683       result_type operator()(first_argument_type iContainer, second_argument_type iIndex) {
0684         return &(iContainer[iIndex]);
0685       }
0686     };
0687 
0688     template <typename T>
0689     struct FindTrait<edmNew::DetSetVector<T>, edmNew::DetSet<T>> {
0690       typedef FindSetForNewDetSetVector<T> value;
0691     };
0692   }  // namespace refhelper
0693      /* ... implementation is provided, just in case it's needed */
0694 }  // namespace edm
0695 
0696 namespace edmNew {
0697   //helper function to make it easier to create a edm::Ref to a new DSV
0698   template <class HandleT>
0699   // inline
0700   edm::Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> makeRefTo(
0701       const HandleT& iHandle, typename HandleT::element_type::value_type::const_iterator itIter) {
0702     static_assert(std::is_same<typename HandleT::element_type,
0703                                DetSetVector<typename HandleT::element_type::value_type::value_type>>::value,
0704                   "Handle and DetSetVector do not have compatible types.");
0705     auto index = itIter - &iHandle->data().front();
0706     return edm::Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>(
0707         iHandle.id(), &(*itIter), index);
0708   }
0709 }  // namespace edmNew
0710 
0711 #include "DataFormats/Common/interface/ContainerMaskTraits.h"
0712 
0713 namespace edm {
0714   template <typename T>
0715   class ContainerMaskTraits<edmNew::DetSetVector<T>> {
0716   public:
0717     typedef T value_type;
0718 
0719     static size_t size(const edmNew::DetSetVector<T>* iContainer) { return iContainer->dataSize(); }
0720     static unsigned int indexFor(const value_type* iElement, const edmNew::DetSetVector<T>* iContainer) {
0721       return iElement - &(iContainer->data().front());
0722     }
0723   };
0724 }  // namespace edm
0725 
0726 // Thinning support
0727 #include "DataFormats/Common/interface/fillCollectionForThinning.h"
0728 namespace edm::detail {
0729   template <typename T>
0730   struct ElementType<edmNew::DetSetVector<T>> {
0731     using type = typename edmNew::DetSetVector<T>::data_type;
0732   };
0733 }  // namespace edm::detail
0734 namespace edmNew {
0735   template <typename T, typename Selector>
0736   void fillCollectionForThinning(edmNew::DetSet<T> const& detset,
0737                                  Selector& selector,
0738                                  unsigned int& iIndex,
0739                                  edmNew::DetSetVector<T>& output,
0740                                  edm::ThinnedAssociation& association) {
0741     typename edmNew::DetSetVector<T>::FastFiller ff(output, detset.detId());
0742     for (auto iter = detset.begin(), end = detset.end(); iter != end; ++iter, ++iIndex) {
0743       edm::detail::fillCollectionForThinning(*iter, selector, iIndex, ff, association);
0744     }
0745     if (detset.begin() != detset.end()) {
0746       // need to decrease the global index by one because the outer loop will increase it
0747       --iIndex;
0748     }
0749   }
0750 }  // namespace edmNew
0751 
0752 #endif