Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:53:01

0001 #ifndef DataFormats_Common_RefCoreWithIndex_h
0002 #define DataFormats_Common_RefCoreWithIndex_h
0003 
0004 /*----------------------------------------------------------------------
0005   
0006 RefCoreWithIndex: The component of edm::Ref containing the product ID and product getter and the index into the collection.
0007     This class is a specialization of RefCore and forwards most of the
0008     implementation to RefCore.
0009 
0010 ----------------------------------------------------------------------*/
0011 #include "DataFormats/Provenance/interface/ProductID.h"
0012 #include "DataFormats/Common/interface/traits.h"
0013 #include "DataFormats/Common/interface/refcore_implementation.h"
0014 #include "DataFormats/Common/interface/RefCore.h"
0015 
0016 #include <algorithm>
0017 #include <typeinfo>
0018 
0019 #include <atomic>
0020 
0021 namespace edm {
0022   class EDProductGetter;
0023   class WrapperBase;
0024 
0025   class RefCoreWithIndex {
0026   public:
0027     RefCoreWithIndex()
0028         : cachePtr_(nullptr), processIndex_(0), productIndex_(0), elementIndex_(edm::key_traits<unsigned int>::value) {}
0029 
0030     RefCoreWithIndex(ProductID const& theId,
0031                      void const* prodPtr,
0032                      EDProductGetter const* prodGetter,
0033                      bool transient,
0034                      unsigned int elementIndex);
0035 
0036     RefCoreWithIndex(RefCore const& iCore, unsigned int);
0037 
0038     RefCoreWithIndex(RefCoreWithIndex const&);
0039 
0040     RefCoreWithIndex& operator=(RefCoreWithIndex const&);
0041 
0042     RefCoreWithIndex(RefCoreWithIndex&& iOther) noexcept
0043         : processIndex_(iOther.processIndex_),
0044           productIndex_(iOther.productIndex_),
0045           elementIndex_(iOther.elementIndex_) {
0046       cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
0047     }
0048 
0049     RefCoreWithIndex& operator=(RefCoreWithIndex&& iOther) noexcept {
0050       cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
0051       processIndex_ = iOther.processIndex_;
0052       productIndex_ = iOther.productIndex_;
0053       elementIndex_ = iOther.elementIndex_;
0054       return *this;
0055     }
0056 
0057     ~RefCoreWithIndex() noexcept {}
0058 
0059     ProductID id() const { ID_IMPL; }
0060 
0061     /**If productPtr is not 0 then productGetter will be 0 since only one is available at a time */
0062     void const* productPtr() const { PRODUCTPTR_IMPL; }
0063 
0064     /**This function is 'const' even though it changes an internal value becuase it is meant to be
0065      used as a way to store in a thread-safe way a cache of a value. This allows classes which use
0066      the RefCore to not have to declare it 'mutable'
0067      */
0068     void setProductPtr(void const* prodPtr) const { setCacheIsProductPtr(prodPtr); }
0069 
0070     /**This function is 'const' even though it changes an internal value becuase it is meant to be
0071      used as a way to store in a thread-safe way a cache of a value. This allows classes which use
0072      the RefCore to not have to declare it 'mutable'
0073      */
0074     bool tryToSetProductPtrForFirstTime(void const* prodPtr) const {
0075       return refcoreimpl::tryToSetCacheItemForFirstTime(cachePtr_, prodPtr);
0076     }
0077 
0078     unsigned int index() const { return elementIndex_; }
0079 
0080     // Checks for null
0081     bool isNull() const { return !isNonnull(); }
0082 
0083     // Checks for non-null
0084     bool isNonnull() const { ISNONNULL_IMPL; }
0085 
0086     // Checks for null
0087     bool operator!() const { return isNull(); }
0088 
0089     // Checks if collection is in memory or available
0090     // in the Event. No type checking is done.
0091 
0092     bool isAvailable() const { return toRefCore().isAvailable(); }
0093 
0094     //Convert to an equivalent RefCore. Needed for Ref specialization.
0095     RefCore const& toRefCore() const { return *reinterpret_cast<const RefCore*>(this); }
0096 
0097     EDProductGetter const* productGetter() const { PRODUCTGETTER_IMPL; }
0098 
0099     void setProductGetter(EDProductGetter const* prodGetter) const { toRefCore().setProductGetter(prodGetter); }
0100 
0101     WrapperBase const* getProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const {
0102       return toRefCore().getProductPtr(type, prodGetter);
0103     }
0104 
0105     void productNotFoundException(std::type_info const& type) const { toRefCore().productNotFoundException(type); }
0106 
0107     void wrongTypeException(std::type_info const& expectedType, std::type_info const& actualType) const {
0108       toRefCore().wrongTypeException(expectedType, actualType);
0109     }
0110 
0111     void nullPointerForTransientException(std::type_info const& type) const {
0112       toRefCore().nullPointerForTransientException(type);
0113     }
0114 
0115     void swap(RefCoreWithIndex&);
0116 
0117     bool isTransient() const { ISTRANSIENT_IMPL; }
0118 
0119     int isTransientInt() const { return isTransient() ? 1 : 0; }
0120 
0121     void pushBackItem(RefCoreWithIndex const& productToBeInserted, bool checkPointer) {
0122       toUnConstRefCore().pushBackItem(productToBeInserted.toRefCore(), checkPointer);
0123     }
0124 
0125   private:
0126     RefCore& toUnConstRefCore() { return *reinterpret_cast<RefCore*>(this); }
0127 
0128     void setId(ProductID const& iId) { toUnConstRefCore().setId(iId); }
0129     void setTransient() { SETTRANSIENT_IMPL; }
0130     void setCacheIsProductPtr(void const* iItem) const { SETCACHEISPRODUCTPTR_IMPL(iItem); }
0131     void setCacheIsProductGetter(EDProductGetter const* iGetter) const { SETCACHEISPRODUCTGETTER_IMPL(iGetter); }
0132 
0133     //NOTE: the order MUST remain the same as a RefCore
0134     // since we play tricks to allow a pointer to a RefCoreWithIndex
0135     // to be the same as a pointer to a RefCore
0136 
0137     //The low bit of the address is used to determine  if the cachePtr_
0138     // is storing the productPtr or the EDProductGetter. The bit is set if
0139     // the address refers to the EDProductGetter.
0140     mutable std::atomic<void const*> cachePtr_;  // transient
0141     //The following is what is stored in a ProductID
0142     // the high bit of processIndex is used to store info on
0143     // if this is transient.
0144     ProcessIndex processIndex_;
0145     ProductIndex productIndex_;
0146     unsigned int elementIndex_;
0147   };
0148 
0149   inline void RefCoreWithIndex::swap(RefCoreWithIndex& other) {
0150     std::swap(processIndex_, other.processIndex_);
0151     std::swap(productIndex_, other.productIndex_);
0152     other.cachePtr_.store(cachePtr_.exchange(other.cachePtr_.load()));
0153     std::swap(elementIndex_, other.elementIndex_);
0154   }
0155 
0156   inline void swap(edm::RefCoreWithIndex& lhs, edm::RefCoreWithIndex& rhs) { lhs.swap(rhs); }
0157 }  // namespace edm
0158 
0159 #endif