CMS 3D CMS Logo

atomic_value_ptr.h
Go to the documentation of this file.
1 #ifndef FWCore_Utilities_atomic_value_ptr_h
2 #define FWCore_Utilities_atomic_value_ptr_h
3 
4 // ----------------------------------------------------------------------
5 //
6 // atomic_value_ptr.h - Smart pointer permitting copying of pointed-to object.
7 //
8 // This is an atomic version of value_ptr.
9 //
10 // The prologue of FWCore/Utilities/interface/value_ptr.h
11 // describes the functionality of value_ptr.
12 //
13 // This allows the value of the pointer to be changed atomically.
14 // Note that copy/move construction and copy/move assignment
15 // are *not* atomic, as an object of type T must be copied or moved.
16 // ----------------------------------------------------------------------
17 
18 #include <atomic>
19 
20 #include <memory>
21 
22 namespace edm {
23 
24  // --------------------------------------------------------------------
25  //
26  // Auxiliary traits class template providing default clone()
27  // Users should specialize this template for types that have their
28  // own self-copy operations; failure to do so may lead to slicing!
29  // User specified clone methods must be thread safe.
30  //
31  // --------------------------------------------------------------------
32 
33  template <typename T>
35  static T* clone(T const* p) { return new T(*p); }
36  };
37 
38  // --------------------------------------------------------------------
39  //
40  // Copyable smart pointer class template using an atomic pointer.
41  //
42  // --------------------------------------------------------------------
43 
44  template <typename T>
46  public:
47  // --------------------------------------------------
48  // Default constructor/destructor:
49  // --------------------------------------------------
50 
52  explicit atomic_value_ptr(T* p) : myP(p) {}
53  ~atomic_value_ptr() { delete myP.load(); }
54 
55  // --------------------------------------------------
56  // Copy constructor/copy assignment:
57  // --------------------------------------------------
58 
59  atomic_value_ptr(atomic_value_ptr const& orig) : myP(createFrom(orig.myP.load())) {}
60 
63  exchangeWithLocal(local);
64  return *this;
65  }
66 
67  atomic_value_ptr(atomic_value_ptr&& orig) : myP(orig.myP.load()) { orig.myP.store(nullptr); }
68 
71  exchangeWithLocal(local);
72  return *this;
73  }
74 
75  // --------------------------------------------------
76  // Access mechanisms:
77  // --------------------------------------------------
78 
79  T& operator*() const { return *myP; }
80  T* operator->() const { return myP.load(); }
81 
82  // --------------------------------------------------
83  // Copy-like construct/assign from compatible atomic_value_ptr<>:
84  // --------------------------------------------------
85 
86  template <typename U>
87  atomic_value_ptr(atomic_value_ptr<U> const& orig) : myP(createFrom(orig.operator->())) {}
88 
89  template <typename U>
92  exchangeWithLocal(local);
93  return *this;
94  }
95 
96  // --------------------------------------------------
97  // move-like construct/assign from unique_ptr<>:
98  // --------------------------------------------------
99 
100  atomic_value_ptr(std::unique_ptr<T> orig) : myP(orig.release()) { orig = nullptr; }
101 
102  atomic_value_ptr& operator=(std::unique_ptr<T> orig) {
104  exchangeWithLocal(local);
105  return *this;
106  }
107 
108  T* load() const { return myP.load(); }
109 
110  bool compare_exchange_strong(T*& oldValue, T* newValue) { return myP.compare_exchange_strong(oldValue, newValue); }
111 
112  // The following typedef, function, and operator definition
113  // support the following syntax:
114  // atomic_value_ptr<T> ptr(..);
115  // if (ptr) { ...
116  // Where the conditional will evaluate as true if and only if the
117  // pointer atomic_value_ptr contains is not null.
118  private:
119  typedef void (atomic_value_ptr::*bool_type)() const;
121 
122  public:
123  operator bool_type() const {
124  return myP != nullptr ? &atomic_value_ptr<T>::this_type_does_not_support_comparisons : nullptr;
125  }
126 
127  private:
128  // --------------------------------------------------
129  // Manipulation:
130  // --------------------------------------------------
131 
132  // This function must be invoked by the object available across threads.
133  // The argument "local" must reference an object local to one thread.
135  T* old = myP.exchange(local.myP.load());
136  local.myP = old;
137  }
138 
139  // --------------------------------------------------
140  // Implementation aid:
141  // --------------------------------------------------
142 
143  template <typename U>
144  static T* createFrom(U const* p) {
145  return p ? atomic_value_ptr_traits<U>::clone(p) : nullptr;
146  }
147 
148  // --------------------------------------------------
149  // Member data:
150  // --------------------------------------------------
151 
152  mutable std::atomic<T*> myP;
153 
154  }; // atomic_value_ptr
155 
156  // Do not allow nonsensical comparisons that the bool_type
157  // conversion operator definition above would otherwise allow.
158  // The function call inside the next 4 operator definitions is
159  // private, so compilation will fail if there is an atempt to
160  // instantiate these 4 operators.
161  template <typename T, typename U>
162  inline bool operator==(atomic_value_ptr<T> const& lhs, U const& rhs) {
164  return false;
165  }
166 
167  template <typename T, typename U>
168  inline bool operator!=(atomic_value_ptr<T> const& lhs, U const& rhs) {
170  return false;
171  }
172 
173  template <typename T, typename U>
174  inline bool operator==(U const& lhs, atomic_value_ptr<T> const& rhs) {
176  return false;
177  }
178 
179  template <typename T, typename U>
180  inline bool operator!=(U const& lhs, atomic_value_ptr<T> const& rhs) {
182  return false;
183  }
184 } // namespace edm
185 
186 #endif // FWCoreUtilities_atomic_value_ptr_h
atomic_value_ptr(atomic_value_ptr< U > const &orig)
atomic_value_ptr & operator=(atomic_value_ptr< U > const &orig)
#define nullptr
void exchangeWithLocal(atomic_value_ptr &local)
atomic_value_ptr & operator=(atomic_value_ptr const &orig)
bool operator==(debugging_allocator< X > const &, debugging_allocator< Y > const &) noexcept
atomic_value_ptr & operator=(std::unique_ptr< T > orig)
void this_type_does_not_support_comparisons() const
atomic_value_ptr & operator=(atomic_value_ptr &&orig)
atomic_value_ptr(atomic_value_ptr const &orig)
bool compare_exchange_strong(T *&oldValue, T *newValue)
bool operator!=(debugging_allocator< X > const &, debugging_allocator< Y > const &) noexcept
static T * createFrom(U const *p)
def load(fileName)
Definition: svgfig.py:547
static T * clone(T const *p)
HLT enums.
std::atomic< T * > myP
atomic_value_ptr(std::unique_ptr< T > orig)
long double T
def move(src, dest)
Definition: eostools.py:511
atomic_value_ptr(atomic_value_ptr &&orig)