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 
34  template <typename T>
36  static T* clone(T const* p) { return new T(*p); }
37  };
38 
39  // --------------------------------------------------------------------
40  //
41  // Copyable smart pointer class template using an atomic pointer.
42  //
43  // --------------------------------------------------------------------
44 
45 
46  template <typename T>
48 
49  public:
50 
51  // --------------------------------------------------
52  // Default constructor/destructor:
53  // --------------------------------------------------
54 
56  explicit atomic_value_ptr(T* p) : myP(p) { }
57  ~atomic_value_ptr() { delete myP.load(); }
58 
59  // --------------------------------------------------
60  // Copy constructor/copy assignment:
61  // --------------------------------------------------
62 
64  myP(createFrom(orig.myP.load())) {
65  }
66 
69  exchangeWithLocal(local);
70  return *this;
71  }
72 
74  myP(orig.myP) { orig.myP.store(nullptr); }
75 
78  exchangeWithLocal(local);
79  return *this;
80  }
81 
82  // --------------------------------------------------
83  // Access mechanisms:
84  // --------------------------------------------------
85 
86  T& operator*() const { return *myP; }
87  T* operator->() const { return myP.load(); }
88 
89  // --------------------------------------------------
90  // Copy-like construct/assign from compatible atomic_value_ptr<>:
91  // --------------------------------------------------
92 
93  template <typename U>
95  myP(createFrom(orig.operator->())) {
96  }
97 
98  template <typename U>
101  exchangeWithLocal(local);
102  return *this;
103  }
104 
105  // --------------------------------------------------
106  // move-like construct/assign from unique_ptr<>:
107  // --------------------------------------------------
108 
109  atomic_value_ptr(std::unique_ptr<T> orig) :
110  myP(orig.release()) {
111  orig = nullptr;
112  }
113 
114  atomic_value_ptr& operator=(std::unique_ptr<T> orig) {
116  exchangeWithLocal(local);
117  return *this;
118  }
119 
120  T* load() const {
121  return myP.load();
122  }
123 
124  bool compare_exchange_strong(T*& oldValue, T* newValue) {
125  return myP.compare_exchange_strong(oldValue, newValue);
126  }
127 
128  // The following typedef, function, and operator definition
129  // support the following syntax:
130  // atomic_value_ptr<T> ptr(..);
131  // if (ptr) { ...
132  // Where the conditional will evaluate as true if and only if the
133  // pointer atomic_value_ptr contains is not null.
134  private:
135  typedef void (atomic_value_ptr::*bool_type)() const;
137 
138  public:
139  operator bool_type() const {
140  return myP != nullptr ?
142  }
143 
144  private:
145 
146  // --------------------------------------------------
147  // Manipulation:
148  // --------------------------------------------------
149 
150  // This function must be invoked by the object available across threads.
151  // The argument "local" must reference an object local to one thread.
153  T* old = myP.exchange(local.myP.load());
154  local.myP = old;
155  }
156 
157  // --------------------------------------------------
158  // Implementation aid:
159  // --------------------------------------------------
160 
161  template <typename U>
162  static T*
163  createFrom(U const* p) {
164  return p
166  : nullptr;
167  }
168 
169  // --------------------------------------------------
170  // Member data:
171  // --------------------------------------------------
172 
173  mutable std::atomic<T*> myP;
174 
175  }; // atomic_value_ptr
176 
177  // Do not allow nonsensical comparisons that the bool_type
178  // conversion operator definition above would otherwise allow.
179  // The function call inside the next 4 operator definitions is
180  // private, so compilation will fail if there is an atempt to
181  // instantiate these 4 operators.
182  template <typename T, typename U>
183  inline bool operator==(atomic_value_ptr<T> const& lhs, U const& rhs) {
185  return false;
186  }
187 
188  template <typename T, typename U>
189  inline bool operator!=(atomic_value_ptr<T> const& lhs, U const& rhs) {
191  return false;
192  }
193 
194  template <typename T, typename U>
195  inline bool operator==(U const& lhs, atomic_value_ptr<T> const& rhs) {
197  return false;
198  }
199 
200  template <typename T, typename U>
201  inline bool operator!=(U const& lhs, atomic_value_ptr<T> const& rhs) {
203  return false;
204  }
205 }
206 
207 
208 #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)
void exchangeWithLocal(atomic_value_ptr &local)
atomic_value_ptr & operator=(atomic_value_ptr const &orig)
#define nullptr
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:546
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:510
atomic_value_ptr(atomic_value_ptr &&orig)