Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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     // This function is potentially costly as it might cause a disk
0092     // read (note that it does not cause the data to be cached locally)
0093     bool isAvailable() const { return toRefCore().isAvailable(); }
0094 
0095     //Convert to an equivalent RefCore. Needed for Ref specialization.
0096     RefCore const& toRefCore() const { return *reinterpret_cast<const RefCore*>(this); }
0097 
0098     EDProductGetter const* productGetter() const { PRODUCTGETTER_IMPL; }
0099 
0100     void setProductGetter(EDProductGetter const* prodGetter) const { toRefCore().setProductGetter(prodGetter); }
0101 
0102     WrapperBase const* getProductPtr(std::type_info const& type, EDProductGetter const* prodGetter) const {
0103       return toRefCore().getProductPtr(type, prodGetter);
0104     }
0105 
0106     void productNotFoundException(std::type_info const& type) const { toRefCore().productNotFoundException(type); }
0107 
0108     void wrongTypeException(std::type_info const& expectedType, std::type_info const& actualType) const {
0109       toRefCore().wrongTypeException(expectedType, actualType);
0110     }
0111 
0112     void nullPointerForTransientException(std::type_info const& type) const {
0113       toRefCore().nullPointerForTransientException(type);
0114     }
0115 
0116     void swap(RefCoreWithIndex&);
0117 
0118     bool isTransient() const { ISTRANSIENT_IMPL; }
0119 
0120     int isTransientInt() const { return isTransient() ? 1 : 0; }
0121 
0122     void pushBackItem(RefCoreWithIndex const& productToBeInserted, bool checkPointer) {
0123       toUnConstRefCore().pushBackItem(productToBeInserted.toRefCore(), checkPointer);
0124     }
0125 
0126   private:
0127     RefCore& toUnConstRefCore() { return *reinterpret_cast<RefCore*>(this); }
0128 
0129     void setId(ProductID const& iId) { toUnConstRefCore().setId(iId); }
0130     void setTransient() { SETTRANSIENT_IMPL; }
0131     void setCacheIsProductPtr(void const* iItem) const { SETCACHEISPRODUCTPTR_IMPL(iItem); }
0132     void setCacheIsProductGetter(EDProductGetter const* iGetter) const { SETCACHEISPRODUCTGETTER_IMPL(iGetter); }
0133 
0134     //NOTE: the order MUST remain the same as a RefCore
0135     // since we play tricks to allow a pointer to a RefCoreWithIndex
0136     // to be the same as a pointer to a RefCore
0137 
0138     //The low bit of the address is used to determine  if the cachePtr_
0139     // is storing the productPtr or the EDProductGetter. The bit is set if
0140     // the address refers to the EDProductGetter.
0141     mutable std::atomic<void const*> cachePtr_;  // transient
0142     //The following is what is stored in a ProductID
0143     // the high bit of processIndex is used to store info on
0144     // if this is transient.
0145     ProcessIndex processIndex_;
0146     ProductIndex productIndex_;
0147     unsigned int elementIndex_;
0148   };
0149 
0150   inline void RefCoreWithIndex::swap(RefCoreWithIndex& other) {
0151     std::swap(processIndex_, other.processIndex_);
0152     std::swap(productIndex_, other.productIndex_);
0153     other.cachePtr_.store(cachePtr_.exchange(other.cachePtr_.load()));
0154     std::swap(elementIndex_, other.elementIndex_);
0155   }
0156 
0157   inline void swap(edm::RefCoreWithIndex& lhs, edm::RefCoreWithIndex& rhs) { lhs.swap(rhs); }
0158 }  // namespace edm
0159 
0160 #endif