Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef DataFormats_Common_refcore_implementation_h
0002 #define DataFormats_Common_refcore_implementation_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     Common
0006 // Class  :     refcore_implementation
0007 //
0008 /**\class refcore_implementation refcore_implementation.h DataFormats/Common/interface/refcore_implementation.h
0009 
0010  Description: provide function implementations to use with both RefCore and RefCoreWithIndex 
0011 
0012  Usage:
0013     RefCore and RefCoreWithIndex are essentially the same except RefCoreWithIndex provides an additional index storage.
0014  Because of the exact way ROOT does storage, RefCoreWithIndex can't be made to inherit from RefCore (without causing meta
0015  data overhead). Therefore the implementations shared by the two classes are contained here.
0016 
0017 */
0018 //
0019 // Original Author:  Chris Jones
0020 //         Created:  Thu Nov  3 09:16:30 CDT 2011
0021 //
0022 
0023 // system include files
0024 #include <limits>
0025 #include <cstdint>
0026 #include <atomic>
0027 
0028 // user include files
0029 
0030 // forward declarations
0031 namespace edm {
0032   class EDProductGetter;
0033 
0034   namespace refcoreimpl {
0035     const unsigned short kTransientBit = 0x8000;
0036     const unsigned short kProcessIndexMask = 0x3FFF;
0037     const std::uintptr_t kCacheIsProductPtrBit = 0x1;
0038     const std::uintptr_t kCacheIsProductPtrMask = std::numeric_limits<std::uintptr_t>::max() ^ kCacheIsProductPtrBit;
0039 
0040     inline bool cacheIsProductPtr(void const* iPtr) {
0041       return 0 == (reinterpret_cast<std::uintptr_t>(iPtr) & refcoreimpl::kCacheIsProductPtrBit);
0042     }
0043 
0044     inline void setCacheIsProductGetter(std::atomic<void const*>& ptr, EDProductGetter const* iGetter) {
0045       std::uintptr_t tmp = reinterpret_cast<std::uintptr_t>(iGetter);
0046       tmp |= refcoreimpl::kCacheIsProductPtrBit;
0047       ptr.store(reinterpret_cast<void const*>(tmp));
0048     }
0049 
0050     //Used by ROOT 5 I/O rule
0051     inline void setCacheIsProductGetter(void const*& ptr, EDProductGetter const* iGetter) {
0052       std::uintptr_t tmp = reinterpret_cast<std::uintptr_t>(iGetter);
0053       tmp |= refcoreimpl::kCacheIsProductPtrBit;
0054       ptr = reinterpret_cast<void const*>(tmp);
0055     }
0056 
0057     inline void setCacheIsItem(std::atomic<void const*>& iCache, void const* iNewValue) { iCache = iNewValue; }
0058 
0059     inline bool tryToSetCacheItemForFirstTime(std::atomic<void const*>& iCache, void const* iNewValue) {
0060       auto cache = iCache.load();
0061       if (not cacheIsProductPtr(cache)) {
0062         return iCache.compare_exchange_strong(cache, iNewValue);
0063       }
0064       return false;
0065     }
0066 
0067     inline void const* productPtr(std::atomic<void const*> const& iCache) {
0068       auto tmp = iCache.load();
0069       return refcoreimpl::cacheIsProductPtr(tmp) ? tmp : static_cast<void const*>(nullptr);
0070     }
0071 
0072     inline EDProductGetter const* productGetter(std::atomic<void const*> const& iCache) {
0073       auto tmp = iCache.load();
0074       return (!refcoreimpl::cacheIsProductPtr(tmp))
0075                  ? reinterpret_cast<EDProductGetter const*>(reinterpret_cast<std::uintptr_t>(tmp) &
0076                                                             refcoreimpl::kCacheIsProductPtrMask)
0077                  : static_cast<EDProductGetter const*>(nullptr);
0078     }
0079 
0080   }  // namespace refcoreimpl
0081 }  // namespace edm
0082 
0083 #define ID_IMPL return ProductID(processIndex_ & refcoreimpl::kProcessIndexMask, productIndex_)
0084 
0085 #define PRODUCTPTR_IMPL return refcoreimpl::productPtr(cachePtr_)
0086 
0087 #define ISNONNULL_IMPL return isTransient() ? productPtr() != nullptr : id().isValid()
0088 
0089 #define PRODUCTGETTER_IMPL return refcoreimpl::productGetter(cachePtr_)
0090 
0091 #define ISTRANSIENT_IMPL return 0 != (processIndex_ & refcoreimpl::kTransientBit)
0092 
0093 #define SETTRANSIENT_IMPL processIndex_ |= refcoreimpl::kTransientBit
0094 
0095 #define SETCACHEISPRODUCTPTR_IMPL(_item_) refcoreimpl::setCacheIsItem(cachePtr_, _item_)
0096 
0097 #define SETCACHEISPRODUCTGETTER_IMPL(_getter_) refcoreimpl::setCacheIsProductGetter(cachePtr_, _getter_)
0098 
0099 #endif