Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-05-23 02:04:52

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