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 #ifndef __GCCXML__
19 #include <atomic>
20 #endif
21 
22 #include <memory>
23 
24 #ifdef __GCCXML__
25 #define nullptr 0
26 #endif
27 
28 namespace edm {
29 
30  // --------------------------------------------------------------------
31  //
32  // Auxiliary traits class template providing default clone()
33  // Users should specialize this template for types that have their
34  // own self-copy operations; failure to do so may lead to slicing!
35  // User specified clone methods must be thread safe.
36  //
37  // --------------------------------------------------------------------
38 
39 
40  template <typename T>
42  static T* clone(T const* p) { return new T(*p); }
43  };
44 
45  // --------------------------------------------------------------------
46  //
47  // Copyable smart pointer class template using an atomic pointer.
48  //
49  // --------------------------------------------------------------------
50 
51 
52  template <typename T>
54 
55  public:
56 
57  // --------------------------------------------------
58  // Default constructor/destructor:
59  // --------------------------------------------------
60 
62  explicit atomic_value_ptr(T* p) : myP(p) { }
63  ~atomic_value_ptr() { delete myP.load(); }
64 
65  // --------------------------------------------------
66  // Copy constructor/copy assignment:
67  // --------------------------------------------------
68 
70  myP(createFrom(orig.myP.load())) {
71  }
72 
74  atomic_value_ptr<T> local(orig);
75  exchangeWithLocal(local);
76  return *this;
77  }
78 
79 #ifndef __GCCXML__
81  myP(orig.myP) { orig.myP.store(nullptr); }
82 
84  atomic_value_ptr<T> local(orig);
85  exchangeWithLocal(local);
86  return *this;
87  }
88 #endif
89 
90  // --------------------------------------------------
91  // Access mechanisms:
92  // --------------------------------------------------
93 
94  T& operator*() const { return *myP; }
95  T* operator->() const { return myP.load(); }
96 
97  // --------------------------------------------------
98  // Copy-like construct/assign from compatible atomic_value_ptr<>:
99  // --------------------------------------------------
100 
101  template <typename U>
103  myP(createFrom(orig.operator->())) {
104  }
105 
106  template <typename U>
108  atomic_value_ptr<T> local(orig);
109  exchangeWithLocal(local);
110  return *this;
111  }
112 
113  // --------------------------------------------------
114  // Copy-like construct/assign from auto_ptr<>:
115  // --------------------------------------------------
116 
117  atomic_value_ptr(std::auto_ptr<T> orig) :
118  myP(orig.release()) {
119  }
120 
121  atomic_value_ptr& operator=(std::auto_ptr<T> orig) {
122  atomic_value_ptr<T> local(orig);
123  exchangeWithLocal(local);
124  return *this;
125  }
126 
127 #ifndef __GCCXML__
128  // --------------------------------------------------
129  // move-like construct/assign from unique_ptr<>:
130  // --------------------------------------------------
131 
132  atomic_value_ptr(std::unique_ptr<T> orig) :
133  myP(orig.release()) {
134  orig = nullptr;
135  }
136 
137  atomic_value_ptr& operator=(std::unique_ptr<T> orig) {
138  atomic_value_ptr<T> local(orig);
139  exchangeWithLocal(local);
140  return *this;
141  }
142 #endif
143 
144  T* load() const {
145  return myP.load();
146  }
147 
148  bool compare_exchange_strong(T*& oldValue, T* newValue) {
149  return myP.compare_exchange_strong(oldValue, newValue);
150  }
151 
152  // The following typedef, function, and operator definition
153  // support the following syntax:
154  // atomic_value_ptr<T> ptr(..);
155  // if (ptr) { ...
156  // Where the conditional will evaluate as true if and only if the
157  // pointer atomic_value_ptr contains is not null.
158  private:
159  typedef void (atomic_value_ptr::*bool_type)() const;
161 
162  public:
163  operator bool_type() const {
164  return myP != nullptr ?
166  }
167 
168  private:
169 
170  // --------------------------------------------------
171  // Manipulation:
172  // --------------------------------------------------
173 
174  // This function must be invoked by the object available across threads.
175  // The argument "local" must reference an object local to one thread.
177  T* old = myP.exchange(local.myP.load());
178  local.myP = old;
179  }
180 
181  // --------------------------------------------------
182  // Implementation aid:
183  // --------------------------------------------------
184 
185  template <typename U>
186  static T*
187  createFrom(U const* p) {
188  return p
190  : nullptr;
191  }
192 
193  // --------------------------------------------------
194  // Member data:
195  // --------------------------------------------------
196 
197 #ifndef __GCCXML__
198  mutable std::atomic<T*> myP;
199 #else
200  T* myP;
201 #endif
202 
203  }; // atomic_value_ptr
204 
205  // Do not allow nonsensical comparisons that the bool_type
206  // conversion operator definition above would otherwise allow.
207  // The function call inside the next 4 operator definitions is
208  // private, so compilation will fail if there is an atempt to
209  // instantiate these 4 operators.
210  template <typename T, typename U>
211  inline bool operator==(atomic_value_ptr<T> const& lhs, U const& rhs) {
213  return false;
214  }
215 
216  template <typename T, typename U>
217  inline bool operator!=(atomic_value_ptr<T> const& lhs, U const& rhs) {
219  return false;
220  }
221 
222  template <typename T, typename U>
223  inline bool operator==(U const& lhs, atomic_value_ptr<T> const& rhs) {
225  return false;
226  }
227 
228  template <typename T, typename U>
229  inline bool operator!=(U const& lhs, atomic_value_ptr<T> const& rhs) {
231  return false;
232  }
233 }
234 
235 
236 #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)
#define nullptr
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)
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)