Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-07-01 02:23:03

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