File indexing completed on 2024-04-06 12:03:50
0001 #ifndef DataFormats_Common_AtomicPtrCache_h
0002 #define DataFormats_Common_AtomicPtrCache_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include <atomic>
0031 #include <memory>
0032
0033
0034
0035
0036 namespace edm {
0037 template <typename T>
0038 class AtomicPtrCache {
0039 public:
0040 AtomicPtrCache();
0041
0042
0043 explicit AtomicPtrCache(T*);
0044
0045
0046 AtomicPtrCache(const AtomicPtrCache<T>&);
0047 AtomicPtrCache& operator=(const AtomicPtrCache<T>&);
0048
0049 ~AtomicPtrCache();
0050
0051
0052 T const* operator->() const { return load(); }
0053 T const& operator*() const { return *load(); }
0054 T const* load() const;
0055
0056 bool isSet() const;
0057
0058
0059 bool set(std::unique_ptr<T> iNewValue) const;
0060
0061
0062
0063 T* operator->() { return load(); }
0064 T& operator*() { return *load(); }
0065
0066 T* load();
0067
0068
0069 void reset();
0070
0071 T* release();
0072
0073 private:
0074
0075 mutable std::atomic<T*> m_data;
0076 };
0077 template <typename T>
0078 inline AtomicPtrCache<T>::AtomicPtrCache() : m_data{nullptr} {}
0079
0080 template <typename T>
0081 inline AtomicPtrCache<T>::AtomicPtrCache(T* iValue) : m_data{iValue} {}
0082
0083 template <typename T>
0084 inline AtomicPtrCache<T>::AtomicPtrCache(const AtomicPtrCache<T>& iOther) : m_data{nullptr} {
0085 auto ptr = iOther.m_data.load(std::memory_order_acquire);
0086 if (ptr != nullptr) {
0087 m_data.store(new T{*ptr}, std::memory_order_release);
0088 }
0089 }
0090 template <typename T>
0091 inline AtomicPtrCache<T>& AtomicPtrCache<T>::operator=(const AtomicPtrCache<T>& iOther) {
0092 auto ptr = iOther.m_data.load(std::memory_order_acquire);
0093 if (ptr != nullptr) {
0094 auto ourPtr = m_data.load(std::memory_order_acquire);
0095 if (ourPtr != nullptr) {
0096 *ourPtr = *ptr;
0097 } else {
0098 m_data.store(new T{*ptr}, std::memory_order_release);
0099 }
0100 } else {
0101 delete m_data.exchange(nullptr, std::memory_order_acq_rel);
0102 }
0103 return *this;
0104 }
0105
0106 template <typename T>
0107 inline AtomicPtrCache<T>::~AtomicPtrCache() {
0108 delete m_data.load(std::memory_order_acquire);
0109 }
0110
0111 template <typename T>
0112 inline T* AtomicPtrCache<T>::load() {
0113 return m_data.load(std::memory_order_acquire);
0114 }
0115
0116 template <typename T>
0117 inline T const* AtomicPtrCache<T>::load() const {
0118 return m_data.load(std::memory_order_acquire);
0119 }
0120
0121 template <typename T>
0122 inline bool AtomicPtrCache<T>::isSet() const {
0123 return nullptr != m_data.load(std::memory_order_acquire);
0124 }
0125
0126 template <typename T>
0127 inline bool AtomicPtrCache<T>::set(std::unique_ptr<T> iNewValue) const {
0128 bool retValue;
0129 T* expected = nullptr;
0130 if ((retValue = m_data.compare_exchange_strong(expected, iNewValue.get(), std::memory_order_acq_rel))) {
0131 iNewValue.release();
0132 }
0133 return retValue;
0134 }
0135
0136 template <typename T>
0137 inline void AtomicPtrCache<T>::reset() {
0138 delete m_data.exchange(nullptr, std::memory_order_acq_rel);
0139 }
0140
0141 template <typename T>
0142 inline T* AtomicPtrCache<T>::release() {
0143 T* tmp = m_data.exchange(nullptr);
0144 return tmp;
0145 }
0146 }
0147 #endif