CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 amd 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 
68  atomic_value_ptr<T> local(orig);
69  exchangeWithLocal(local);
70  return *this;
71  }
72 
74  myP(orig.myP) { orig.myP.store(nullptr); }
75 
77  atomic_value_ptr<T> local(orig);
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>
100  atomic_value_ptr<T> local(orig);
101  exchangeWithLocal(local);
102  return *this;
103  }
104 
105  // --------------------------------------------------
106  // Copy-like construct/assign from auto_ptr<>:
107  // --------------------------------------------------
108 
109  atomic_value_ptr(std::auto_ptr<T> orig) :
110  myP(orig.release()) {
111  }
112 
113  atomic_value_ptr& operator=(std::auto_ptr<T> orig) {
114  atomic_value_ptr<T> local(orig);
115  exchangeWithLocal(local);
116  return *this;
117  }
118 
119  // --------------------------------------------------
120  // move-like construct/assign from unique_ptr<>:
121  // --------------------------------------------------
122 
123  atomic_value_ptr(std::unique_ptr<T> orig) :
124  myP(orig.release()) {
125  orig = nullptr;
126  }
127 
128  atomic_value_ptr& operator=(std::unique_ptr<T> orig) {
129  atomic_value_ptr<T> local(orig);
130  exchangeWithLocal(local);
131  return *this;
132  }
133 
134  T* load() const {
135  return myP.load();
136  }
137 
138  bool compare_exchange_strong(T*& oldValue, T* newValue) {
139  return myP.compare_exchange_strong(oldValue, newValue);
140  }
141 
142  // The following typedef, function, and operator definition
143  // support the following syntax:
144  // atomic_value_ptr<T> ptr(..);
145  // if (ptr) { ...
146  // Where the conditional will evaluate as true if and only if the
147  // pointer atomic_value_ptr contains is not null.
148  private:
149  typedef void (atomic_value_ptr::*bool_type)() const;
151 
152  public:
153  operator bool_type() const {
154  return myP != nullptr ?
156  }
157 
158  private:
159 
160  // --------------------------------------------------
161  // Manipulation:
162  // --------------------------------------------------
163 
164  // This function must be invoked by the object available across threads.
165  // The argument "local" must reference an object local to one thread.
167  T* old = myP.exchange(local.myP.load());
168  local.myP = old;
169  }
170 
171  // --------------------------------------------------
172  // Implementation aid:
173  // --------------------------------------------------
174 
175  template <typename U>
176  static T*
177  createFrom(U const* p) {
178  return p
180  : nullptr;
181  }
182 
183  // --------------------------------------------------
184  // Member data:
185  // --------------------------------------------------
186 
187  mutable std::atomic<T*> myP;
188 
189  }; // atomic_value_ptr
190 
191  // Do not allow nonsensical comparisons that the bool_type
192  // conversion operator definition above would otherwise allow.
193  // The function call inside the next 4 operator definitions is
194  // private, so compilation will fail if there is an atempt to
195  // instantiate these 4 operators.
196  template <typename T, typename U>
197  inline bool operator==(atomic_value_ptr<T> const& lhs, U const& rhs) {
199  return false;
200  }
201 
202  template <typename T, typename U>
203  inline bool operator!=(atomic_value_ptr<T> const& lhs, U const& rhs) {
205  return false;
206  }
207 
208  template <typename T, typename U>
209  inline bool operator==(U const& lhs, atomic_value_ptr<T> const& rhs) {
211  return false;
212  }
213 
214  template <typename T, typename U>
215  inline bool operator!=(U const& lhs, atomic_value_ptr<T> const& rhs) {
217  return false;
218  }
219 }
220 
221 
222 #endif // FWCoreUtilities_atomic_value_ptr_h
atomic_value_ptr(atomic_value_ptr< U > const &orig)
atomic_value_ptr(std::auto_ptr< T > orig)
atomic_value_ptr & operator=(atomic_value_ptr< U > const &orig)
void exchangeWithLocal(atomic_value_ptr &local)
bool operator!=(debugging_allocator< X > const &, debugging_allocator< Y > const &)
atomic_value_ptr & operator=(atomic_value_ptr const &orig)
#define nullptr
void(atomic_value_ptr::* bool_type)() const
atomic_value_ptr & operator=(std::unique_ptr< T > orig)
bool operator==(debugging_allocator< X > const &, debugging_allocator< Y > const &)
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)
static T * createFrom(U const *p)
atomic_value_ptr & operator=(std::auto_ptr< T > orig)
static T * clone(T const *p)
std::atomic< T * > myP
atomic_value_ptr(std::unique_ptr< T > orig)
long double T
atomic_value_ptr(atomic_value_ptr &&orig)