Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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