Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 // -*- C++ -*-
0002 //
0003 // Package:     Common
0004 // Class  :     PtrVectorBase
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Wed Oct 24 15:49:27 EDT 2007
0011 //
0012 
0013 // user include files
0014 #include "DataFormats/Common/interface/WrapperBase.h"
0015 #include "DataFormats/Common/interface/PtrVectorBase.h"
0016 #include "DataFormats/Common/interface/traits.h"
0017 #include "DataFormats/Common/interface/EDProductGetter.h"
0018 #include "FWCore/Utilities/interface/EDMException.h"
0019 #include "FWCore/Utilities/interface/Exception.h"
0020 
0021 // system include files
0022 #include <ostream>
0023 
0024 //
0025 // constants, enums and typedefs
0026 //
0027 namespace edm {
0028   //
0029   // static data member definitions
0030   //
0031 
0032   //
0033   // constructor and destructor
0034   //
0035   PtrVectorBase::PtrVectorBase() : cachedItems_(nullptr) {}
0036 
0037   PtrVectorBase::~PtrVectorBase() { delete cachedItems_.load(); }
0038 
0039   PtrVectorBase::PtrVectorBase(const PtrVectorBase& iOther)
0040       : core_(iOther.core_), indicies_(iOther.indicies_), cachedItems_(nullptr) {
0041     auto cache = iOther.cachedItems_.load();
0042     if (cache) {
0043       cachedItems_.store(new std::vector<void const*>(*cache));
0044     }
0045   }
0046 
0047   //
0048   // assignment operators
0049   //
0050 
0051   //
0052   // member functions
0053   //
0054 
0055   /// swap
0056   void PtrVectorBase::swap(PtrVectorBase& other) {
0057     core_.swap(other.core_);
0058     indicies_.swap(other.indicies_);
0059     other.cachedItems_.store(cachedItems_.exchange(other.cachedItems_.load()));
0060   }
0061 
0062   void PtrVectorBase::push_back_base(RefCore const& core, key_type iKey, void const* iData) {
0063     core_.pushBackItem(core, false);
0064     //Did we already push a 'non-cached' Ptr into the container or is this a 'non-cached' Ptr?
0065     if (not cachedItems_ and indicies_.empty()) {
0066       cachedItems_.store(new std::vector<void const*>());
0067       (*cachedItems_).reserve(indicies_.capacity());
0068     }
0069     auto tmpCachedItems = cachedItems_.load();
0070     if (tmpCachedItems and (indicies_.size() == (*tmpCachedItems).size())) {
0071       if (iData) {
0072         tmpCachedItems->push_back(iData);
0073       } else if (key_traits<key_type>::value == iKey) {
0074         tmpCachedItems->push_back(nullptr);
0075       } else {
0076         delete tmpCachedItems;
0077         cachedItems_.store(nullptr);
0078       }
0079     }
0080     indicies_.push_back(iKey);
0081   }
0082 
0083   bool PtrVectorBase::isAvailable() const {
0084     if (indicies_.empty()) {
0085       return core_.isAvailable();
0086     }
0087     if (!hasCache()) {
0088       if (!id().isValid() || productGetter() == nullptr) {
0089         return false;
0090       }
0091       getProduct_();
0092     }
0093     auto tmpCachedItems = cachedItems_.load();
0094     for (auto ptr : *tmpCachedItems) {
0095       if (ptr == nullptr) {
0096         return false;
0097       }
0098     }
0099     return true;
0100   }
0101 
0102   //
0103   // const member functions
0104   //
0105   void PtrVectorBase::getProduct_() const {
0106     if (hasCache()) {
0107       return;
0108     }
0109     if (indicies_.empty()) {
0110       return;
0111     }
0112     //NOTE: Another thread could be getting the data
0113     auto tmpProductGetter = productGetter();
0114     if (nullptr == tmpProductGetter) {
0115       throw Exception(errors::LogicError) << "Tried to get data for a PtrVector which has no EDProductGetter\n";
0116     }
0117     WrapperBase const* product = tmpProductGetter->getIt(id());
0118 
0119     auto tmpCachedItems = std::make_unique<std::vector<void const*>>();
0120 
0121     if (product != nullptr) {
0122       product->fillPtrVector(typeInfo(), indicies_, *tmpCachedItems);
0123 
0124       std::vector<void const*>* expected = nullptr;
0125       if (cachedItems_.compare_exchange_strong(expected, tmpCachedItems.get())) {
0126         //we were the first thread to change the value
0127         tmpCachedItems.release();
0128       }
0129 
0130       return;
0131     }
0132 
0133     tmpCachedItems->resize(indicies_.size(), nullptr);
0134 
0135     std::vector<unsigned int> thinnedKeys;
0136     thinnedKeys.assign(indicies_.begin(), indicies_.end());
0137     std::vector<WrapperBase const*> wrappers(indicies_.size(), nullptr);
0138     tmpProductGetter->getThinnedProducts(id(), wrappers, thinnedKeys);
0139     unsigned int nWrappers = wrappers.size();
0140     assert(wrappers.size() == indicies_.size());
0141     assert(wrappers.size() == tmpCachedItems->size());
0142     for (unsigned k = 0; k < nWrappers; ++k) {
0143       if (wrappers[k] != nullptr) {
0144         wrappers[k]->setPtr(typeInfo(), thinnedKeys[k], (*tmpCachedItems)[k]);
0145       }
0146     }
0147     {
0148       std::vector<void const*>* expected = nullptr;
0149       if (cachedItems_.compare_exchange_strong(expected, tmpCachedItems.get())) {
0150         //we were the first thread to change the value
0151         tmpCachedItems.release();
0152       }
0153     }
0154   }
0155 
0156   bool PtrVectorBase::checkCachedItems() const {
0157     auto tmp = cachedItems_.load();
0158     if (not tmp) {
0159       return false;
0160     }
0161     for (auto item : *tmp) {
0162       if (item == nullptr) {
0163         throw Exception(errors::InvalidReference)
0164             << "Asked for data from a PtrVector which refers to a non-existent product with ProductID " << id() << "\n";
0165       }
0166     }
0167     return true;
0168   }
0169 
0170   bool PtrVectorBase::operator==(PtrVectorBase const& iRHS) const {
0171     if (core_ != iRHS.core_) {
0172       return false;
0173     }
0174     if (indicies_.size() != iRHS.indicies_.size()) {
0175       return false;
0176     }
0177     return std::equal(indicies_.begin(), indicies_.end(), iRHS.indicies_.begin());
0178   }
0179 
0180   //
0181   // static member functions
0182   //
0183 
0184   static const std::vector<void const*> s_emptyCache{};
0185 
0186   const std::vector<void const*>& PtrVectorBase::emptyCache() { return s_emptyCache; }
0187 
0188 }  // namespace edm