Geant4  10.02.p01
G4atomic.hh
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
28 //
29 //
30 // $Id: G4atomic.hh 93110 2015-11-05 08:37:42Z jmadsen $
31 //
32 //
63 //
64 //
65 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
66 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
67 
68 
69 #ifndef G4atomic_hh_
70 #define G4atomic_hh_
71 
72 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
73 
74 #ifdef G4MULTITHREADED
75 
76 #include "G4atomic_defines.hh"
77 
78 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
79 
80 template<typename _Tp>
81 class G4atomic
82 {
83 public:
84  typedef typename std::atomic<_Tp> base_type;
85  typedef _Tp value_type;
86 
87 private:
88  using mem_odr = std::memory_order;
89 
90 public:
91  // constructors
92  explicit
93  G4atomic(mem_odr odr = std::memory_order_acq_rel) : fMemOrder(odr)
94  { atomics::set(&fvalue, value_type()); }
95 
96  explicit
97  G4atomic(const value_type& _init,
98  mem_odr odr = std::memory_order_acq_rel) : fMemOrder(odr)
99  { atomics::set(&fvalue, _init); }
100 
101  // copy-constructor from pure C++11 atomic
102  explicit
103  G4atomic(const base_type& rhs,
104  mem_odr odr = std::memory_order_acq_rel) : fMemOrder(odr)
105  { atomics::set(&fvalue, rhs); }
106 
107  // copy-constructor
108  explicit
109  G4atomic(const G4atomic& rhs) : fMemOrder(rhs.fMemOrder)
110  { atomics::set(&fvalue, rhs.base()); }
111 
112  // assignment operators
113  G4atomic& operator=(const G4atomic& rhs)
114  {
115  if(this != &rhs)
116  atomics::set(&fvalue, rhs.fvalue);
117  return *this;
118  }
119 
120  G4atomic& operator=(const value_type& rhs)
121  {
122  atomics::set(&fvalue, rhs);
123  return *this;
124  }
125 
126  G4atomic& operator=(const base_type& rhs)
127  {
128  atomics::set(&fvalue, rhs);
129  return *this;
130  }
131 
132  // destructor
133  ~G4atomic() { fvalue.~base_type(); }
134 
135  // base version
136  base_type& base() { return fvalue; }
137  const base_type& base() const { return fvalue; }
138  base_type& base() volatile { return fvalue; }
139  const base_type& base() const volatile { return fvalue; }
140 
141  // check if atomic is lock-free
142  bool is_lock_free() const { return fvalue.is_lock_free(); }
143  bool is_lock_free() const volatile { return fvalue.is_lock_free(); }
144 
145  // store functions
146  void store(_Tp _desired, std::memory_order mem_odr
147  = std::memory_order_seq_cst)
148  { atomics::set(fvalue, _desired, mem_odr); }
149  void store(_Tp _desired, std::memory_order mem_odr
150  = std::memory_order_seq_cst) volatile
151  { atomics::set(fvalue, _desired, mem_odr); }
152 
153  // load functions
154  _Tp load(std::memory_order mem_odr
155  = std::memory_order_seq_cst) const
156  { return atomics::get(fvalue, mem_odr); }
157  _Tp load(std::memory_order mem_odr
158  = std::memory_order_seq_cst) const volatile
159  { return atomics::get(fvalue, mem_odr); }
160 
161  // implicit conversion functions
162  operator _Tp() const { return this->load(); }
163  operator _Tp() const volatile { return this->load(); }
164 
165  operator base_type&() const { return fvalue; }
166 
167  // compare-and-swap functions
168  bool compare_exchange_weak(_Tp& _expected, _Tp _desired,
169  std::memory_order _success,
170  std::memory_order _failure)
171  { return fvalue.compare_exchange_weak(_expected, _desired,
172  _success, _failure); }
173  bool compare_exchange_weak(_Tp& _expected, _Tp _desired,
174  std::memory_order _success,
175  std::memory_order _failure) volatile
176  { return fvalue.compare_exchange_weak(_expected, _desired,
177  _success, _failure); }
178 
179  bool compare_exchange_weak(_Tp& _expected, _Tp _desired,
180  std::memory_order _order)
181  { return fvalue.compare_exchange_weak(_expected, _desired, _order); }
182  bool compare_exchange_weak(_Tp& _expected, _Tp _desired,
183  std::memory_order _order) volatile
184  { return fvalue.compare_exchange_weak(_expected, _desired, _order); }
185 
186  bool compare_exchange_strong(_Tp& _expected, _Tp _desired,
187  std::memory_order _success,
188  std::memory_order _failure)
189  { return fvalue.compare_exchange_weak(_expected, _desired,
190  _success, _failure); }
191  bool compare_exchange_strong(_Tp& _expected, _Tp _desired,
192  std::memory_order _success,
193  std::memory_order _failure) volatile
194  { return fvalue.compare_exchange_weak(_expected, _desired,
195  _success, _failure); }
196 
197  bool compare_exchange_strong(_Tp& _expected, _Tp _desired,
198  std::memory_order _order)
199  { return fvalue.compare_exchange_weak(_expected, _desired, _order); }
200  bool compare_exchange_strong(_Tp& _expected, _Tp _desired,
201  std::memory_order _order) volatile
202  { return fvalue.compare_exchange_weak(_expected, _desired, _order); }
203 
204  // value_type operators
205  G4atomic& operator+=(const value_type& rhs)
206  { atomics::increment(&fvalue, rhs, fMemOrder); return *this; }
207  G4atomic& operator-=(const value_type& rhs)
208  { atomics::decrement(&fvalue, rhs, fMemOrder); return *this; }
209  G4atomic& operator*=(const value_type& rhs)
210  { atomics::multiply(&fvalue, rhs, fMemOrder); return *this; }
211  G4atomic& operator/=(const value_type& rhs)
212  { atomics::divide(&fvalue, rhs, fMemOrder); return *this; }
213 
214  // atomic operators
215  G4atomic& operator+=(const G4atomic& rhs)
216  { atomics::increment(&fvalue, rhs.fvalue); return *this; }
217  G4atomic& operator-=(const G4atomic& rhs)
218  { atomics::decrement(&fvalue, rhs.fvalue); return *this; }
219  G4atomic& operator*=(const G4atomic& rhs)
220  { atomics::multiply(&fvalue, rhs.fvalue); return *this; }
221  G4atomic& operator/=(const G4atomic& rhs)
222  { atomics::divide(&fvalue, rhs.fvalue); return *this; }
223 
224  G4atomic& operator+=(const G4atomic& rhs) volatile
225  { atomics::increment(&fvalue, rhs.fvalue); return *this; }
226  G4atomic& operator-=(const G4atomic& rhs) volatile
227  { atomics::decrement(&fvalue, rhs.fvalue); return *this; }
228  G4atomic& operator*=(const G4atomic& rhs) volatile
229  { atomics::multiply(&fvalue, rhs.fvalue); return *this; }
230  G4atomic& operator/=(const G4atomic& rhs) volatile
231  { atomics::divide(&fvalue, rhs.fvalue); return *this; }
232 
233  // STL atomic operators
234  G4atomic& operator+=(const std::atomic<_Tp>& rhs)
235  { atomics::increment(&fvalue, rhs, fMemOrder); return *this; }
236  G4atomic& operator-=(const std::atomic<_Tp>& rhs)
237  { atomics::decrement(&fvalue, rhs, fMemOrder); return *this; }
238  G4atomic& operator*=(const std::atomic<_Tp>& rhs)
239  { atomics::multiply(&fvalue, rhs, fMemOrder); return *this; }
240  G4atomic& operator/=(const std::atomic<_Tp>& rhs)
241  { atomics::divide(&fvalue, rhs, fMemOrder); return *this; }
242 
243  G4atomic& operator+=(const std::atomic<_Tp>& rhs) volatile
244  { atomics::increment(&fvalue, rhs, fMemOrder); return *this; }
245  G4atomic& operator-=(const std::atomic<_Tp>& rhs) volatile
246  { atomics::decrement(&fvalue, rhs, fMemOrder); return *this; }
247  G4atomic& operator*=(const std::atomic<_Tp>& rhs) volatile
248  { atomics::multiply(&fvalue, rhs, fMemOrder); return *this; }
249  G4atomic& operator/=(const std::atomic<_Tp>& rhs) volatile
250  { atomics::divide(&fvalue, rhs, fMemOrder); return *this; }
251 
252  // increment operators
253  value_type operator++() { value_type _tmp = ++fvalue; return _tmp; }
254  value_type operator++(int)
255  { value_type _tmp = fvalue++; return _tmp; }
256 
257  value_type operator--() { value_type _tmp = --fvalue; return _tmp; }
258  value_type operator--(int)
259  { value_type _tmp = fvalue--; return _tmp; }
260 
261 protected:
262  base_type fvalue;
263  mem_odr fMemOrder;
264 
265 };
266 
267 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
268 
269 #else // ! G4MULTITHREADED
270 
271 template <typename _Tp> using G4atomic = _Tp;
272 
273 #endif // G4MULTITHREADED
274 
275 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
276 
277 #endif // G4atomic_hh_
_Tp G4atomic
This is an friendly implementation of the STL atomic class. This class has the same interface as the ...
Definition: G4atomic.hh:271