Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-27 02:49:59

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     /**No checks are done: id must be valid; transient bit is not set  */
0037     RefCoreWithIndex(ProductID const& id, void const* prodPtr, unsigned int index)
0038         : cachePtr_(prodPtr),
0039           processIndex_(id.processIndex()),
0040           productIndex_(id.productIndex()),
0041           elementIndex_(index) {}
0042 
0043     RefCoreWithIndex(RefCore const& iCore, unsigned int);
0044 
0045     RefCoreWithIndex(RefCoreWithIndex const&);
0046 
0047     RefCoreWithIndex& operator=(RefCoreWithIndex const&);
0048 
0049     RefCoreWithIndex(RefCoreWithIndex&& iOther) noexcept
0050         : processIndex_(iOther.processIndex_),
0051           productIndex_(iOther.productIndex_),
0052           elementIndex_(iOther.elementIndex_) {
0053       cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
0054     }
0055 
0056     RefCoreWithIndex& operator=(RefCoreWithIndex&& iOther) noexcept {
0057       cachePtr_.store(iOther.cachePtr_.load(std::memory_order_relaxed), std::memory_order_relaxed);
0058       processIndex_ = iOther.processIndex_;
0059       productIndex_ = iOther.productIndex_;
0060       elementIndex_ = iOther.elementIndex_;
0061       return *this;
0062     }
0063 
0064     ~RefCoreWithIndex() noexcept {}
0065 
0066     ProductID id() const { ID_IMPL; }
0067 
0068     /**If productPtr is not 0 then productGetter will be 0 since only one is available at a time */
0069     void const* productPtr() const { PRODUCTPTR_IMPL; }
0070 
0071     /**This function is 'const' even though it changes an internal value becuase it is meant to be
0072      used as a way to store in a thread-safe way a cache of a value. This allows classes which use
0073      the RefCore to not have to declare it 'mutable'
0074      */
0075     void setProductPtr(void const* prodPtr) const { setCacheIsProductPtr(prodPtr); }
0076 
0077     /**This function is 'const' even though it changes an internal value becuase it is meant to be
0078      used as a way to store in a thread-safe way a cache of a value. This allows classes which use
0079      the RefCore to not have to declare it 'mutable'
0080      */
0081     bool tryToSetProductPtrForFirstTime(void const* prodPtr) const {
0082       return refcoreimpl::tryToSetCacheItemForFirstTime(cachePtr_, prodPtr);
0083     }
0084 
0085     unsigned int index() const { return elementIndex_; }
0086 
0087     // Checks for null
0088     bool isNull() const { return !isNonnull(); }
0089 
0090     // Checks for non-null
0091     bool isNonnull() const { ISNONNULL_IMPL; }
0092 
0093     // Checks for null
0094     bool operator!() const { return isNull(); }
0095 
0096     // Checks if collection is in memory or available
0097     // in the Event. No type checking is done.
0098     // This function is potentially costly as it might cause a disk
0099     // read (note that it does not cause the data to be cached locally)
0100     bool isAvailable() const { return toRefCore().isAvailable(); }
0101 
0102     //Convert to an equivalent RefCore. Needed for Ref specialization.
0103     RefCore const& toRefCore() const { return *reinterpret_cast<const RefCore*>(this); }
0104 
0105     EDProductGetter const* productGetter() const { PRODUCTGETTER_IMPL; }
0106 
0107     void setProductGetter(EDProductGetter const* prodGetter) const { toRefCore().setProductGetter(prodGetter); }
0108 
0109     WrapperBase const* getProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const {
0110       return toRefCore().getProductPtr(type, prodGetter);
0111     }
0112 
0113     void productNotFoundException(std::type_info const& type) const { toRefCore().productNotFoundException(type); }
0114 
0115     void wrongTypeException(std::type_info const& expectedType, std::type_info const& actualType) const {
0116       toRefCore().wrongTypeException(expectedType, actualType);
0117     }
0118 
0119     void nullPointerForTransientException(std::type_info const& type) const {
0120       toRefCore().nullPointerForTransientException(type);
0121     }
0122 
0123     void swap(RefCoreWithIndex&);
0124 
0125     bool isTransient() const { ISTRANSIENT_IMPL; }
0126 
0127     int isTransientInt() const { return isTransient() ? 1 : 0; }
0128 
0129     void pushBackItem(RefCoreWithIndex const& productToBeInserted, bool checkPointer) {
0130       toUnConstRefCore().pushBackItem(productToBeInserted.toRefCore(), checkPointer);
0131     }
0132 
0133   private:
0134     RefCore& toUnConstRefCore() { return *reinterpret_cast<RefCore*>(this); }
0135 
0136     void setId(ProductID const& iId) { toUnConstRefCore().setId(iId); }
0137     void setTransient() { SETTRANSIENT_IMPL; }
0138     void setCacheIsProductPtr(void const* iItem) const { SETCACHEISPRODUCTPTR_IMPL(iItem); }
0139     void setCacheIsProductGetter(EDProductGetter const* iGetter) const { SETCACHEISPRODUCTGETTER_IMPL(iGetter); }
0140 
0141     //NOTE: the order MUST remain the same as a RefCore
0142     // since we play tricks to allow a pointer to a RefCoreWithIndex
0143     // to be the same as a pointer to a RefCore
0144 
0145     //The low bit of the address is used to determine  if the cachePtr_
0146     // is storing the productPtr or the EDProductGetter. The bit is set if
0147     // the address refers to the EDProductGetter.
0148     mutable std::atomic<void const*> cachePtr_;  // transient
0149     //The following is what is stored in a ProductID
0150     // the high bit of processIndex is used to store info on
0151     // if this is transient.
0152     ProcessIndex processIndex_;
0153     ProductIndex productIndex_;
0154     unsigned int elementIndex_;
0155   };
0156 
0157   inline void RefCoreWithIndex::swap(RefCoreWithIndex& other) {
0158     std::swap(processIndex_, other.processIndex_);
0159     std::swap(productIndex_, other.productIndex_);
0160     other.cachePtr_.store(cachePtr_.exchange(other.cachePtr_.load()));
0161     std::swap(elementIndex_, other.elementIndex_);
0162   }
0163 
0164   inline void swap(edm::RefCoreWithIndex& lhs, edm::RefCoreWithIndex& rhs) { lhs.swap(rhs); }
0165 }  // namespace edm
0166 
0167 #endif