File indexing completed on 2024-04-06 12:13:11
0001 #ifndef FWCore_Utilities_atomic_value_ptr_h
0002 #define FWCore_Utilities_atomic_value_ptr_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <atomic>
0019
0020 #include <memory>
0021
0022 namespace edm {
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 template <typename T>
0034 struct atomic_value_ptr_traits {
0035 static T* clone(T const* p) { return new T(*p); }
0036 };
0037
0038
0039
0040
0041
0042
0043
0044 template <typename T>
0045 class atomic_value_ptr {
0046 public:
0047
0048
0049
0050
0051 atomic_value_ptr() : myP(nullptr) {}
0052 explicit atomic_value_ptr(T* p) : myP(p) {}
0053 ~atomic_value_ptr() { delete myP.load(); }
0054
0055
0056
0057
0058
0059 atomic_value_ptr(atomic_value_ptr const& orig) : myP(createFrom(orig.myP.load())) {}
0060
0061 atomic_value_ptr& operator=(atomic_value_ptr const& orig) {
0062 atomic_value_ptr<T> local(orig);
0063 exchangeWithLocal(local);
0064 return *this;
0065 }
0066
0067 atomic_value_ptr(atomic_value_ptr&& orig) : myP(orig.myP.load()) { orig.myP.store(nullptr); }
0068
0069 atomic_value_ptr& operator=(atomic_value_ptr&& orig) {
0070 atomic_value_ptr<T> local(orig);
0071 exchangeWithLocal(local);
0072 return *this;
0073 }
0074
0075
0076
0077
0078
0079 T& operator*() const { return *myP; }
0080 T* operator->() const { return myP.load(); }
0081
0082
0083
0084
0085
0086 template <typename U>
0087 atomic_value_ptr(atomic_value_ptr<U> const& orig) : myP(createFrom(orig.operator->())) {}
0088
0089 template <typename U>
0090 atomic_value_ptr& operator=(atomic_value_ptr<U> const& orig) {
0091 atomic_value_ptr<T> local(orig);
0092 exchangeWithLocal(local);
0093 return *this;
0094 }
0095
0096
0097
0098
0099
0100 atomic_value_ptr(std::unique_ptr<T> orig) : myP(orig.release()) { orig = nullptr; }
0101
0102 atomic_value_ptr& operator=(std::unique_ptr<T> orig) {
0103 atomic_value_ptr<T> local(std::move(orig));
0104 exchangeWithLocal(local);
0105 return *this;
0106 }
0107
0108 T* load() const { return myP.load(); }
0109
0110 bool compare_exchange_strong(T*& oldValue, T* newValue) { return myP.compare_exchange_strong(oldValue, newValue); }
0111
0112
0113
0114
0115
0116
0117
0118 private:
0119 typedef void (atomic_value_ptr::*bool_type)() const;
0120 void this_type_does_not_support_comparisons() const {}
0121
0122 public:
0123 operator bool_type() const {
0124 return myP != nullptr ? &atomic_value_ptr<T>::this_type_does_not_support_comparisons : nullptr;
0125 }
0126
0127 private:
0128
0129
0130
0131
0132
0133
0134 void exchangeWithLocal(atomic_value_ptr& local) {
0135 T* old = myP.exchange(local.myP.load());
0136 local.myP = old;
0137 }
0138
0139
0140
0141
0142
0143 template <typename U>
0144 static T* createFrom(U const* p) {
0145 return p ? atomic_value_ptr_traits<U>::clone(p) : nullptr;
0146 }
0147
0148
0149
0150
0151
0152 mutable std::atomic<T*> myP;
0153
0154 };
0155
0156
0157
0158
0159
0160
0161 template <typename T, typename U>
0162 inline bool operator==(atomic_value_ptr<T> const& lhs, U const& rhs) {
0163 lhs.this_type_does_not_support_comparisons();
0164 return false;
0165 }
0166
0167 template <typename T, typename U>
0168 inline bool operator!=(atomic_value_ptr<T> const& lhs, U const& rhs) {
0169 lhs.this_type_does_not_support_comparisons();
0170 return false;
0171 }
0172
0173 template <typename T, typename U>
0174 inline bool operator==(U const& lhs, atomic_value_ptr<T> const& rhs) {
0175 rhs.this_type_does_not_support_comparisons();
0176 return false;
0177 }
0178
0179 template <typename T, typename U>
0180 inline bool operator!=(U const& lhs, atomic_value_ptr<T> const& rhs) {
0181 rhs.this_type_does_not_support_comparisons();
0182 return false;
0183 }
0184 }
0185
0186 #endif