ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4atomic.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4atomic.hh
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 //
31 //
62 //
63 //
64 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
65 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
66 
67 
68 #ifndef G4atomic_hh_
69 #define G4atomic_hh_
70 
71 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
72 
73 #ifdef G4MULTITHREADED
74 
75 #include "G4atomic_defines.hh"
76 
77 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
78 
79 template<typename _Tp>
80 class G4atomic
81 {
82  public:
83 
84  typedef typename std::atomic<_Tp> base_type;
85  typedef _Tp value_type;
86 
87  private:
88 
89  using mem_ord = std::memory_order;
90 
91  public:
92 
93  // constructors
94  explicit
95  G4atomic(mem_ord mo = std::memory_order_acq_rel) : fMemOrder(mo)
96  { atomics::set(&fvalue, value_type()); }
97 
98  explicit
99  G4atomic(const value_type& _init,
100  mem_ord mo = std::memory_order_acq_rel) : fMemOrder(mo)
101  { atomics::set(&fvalue, _init); }
102 
103  // copy-constructor from pure C++11 atomic
104  explicit
105  G4atomic(const base_type& rhs,
106  mem_ord mo = std::memory_order_acq_rel) : fMemOrder(mo)
107  { atomics::set(&fvalue, rhs); }
108 
109  // copy-constructor
110  explicit
111  G4atomic(const G4atomic& rhs) : fMemOrder(rhs.fMemOrder)
112  { atomics::set(&fvalue, rhs.base()); }
113 
114  // assignment operators
115  G4atomic& operator=(const G4atomic& rhs)
116  {
117  if(this != &rhs)
118  atomics::set(&fvalue, rhs.fvalue);
119  return *this;
120  }
121 
122  G4atomic& operator=(const value_type& rhs)
123  {
124  atomics::set(&fvalue, rhs);
125  return *this;
126  }
127 
128  G4atomic& operator=(const base_type& rhs)
129  {
130  atomics::set(&fvalue, rhs);
131  return *this;
132  }
133 
134  // destructor
135  ~G4atomic() { fvalue.~base_type(); }
136 
137  // base version
138  base_type& base() { return fvalue; }
139  const base_type& base() const { return fvalue; }
140  base_type& base() volatile { return fvalue; }
141  const base_type& base() const volatile { return fvalue; }
142 
143  // check if atomic is lock-free
144  bool is_lock_free() const { return fvalue.is_lock_free(); }
145  bool is_lock_free() const volatile { return fvalue.is_lock_free(); }
146 
147  // store functions
148  void store(_Tp _desired, mem_ord mo = std::memory_order_seq_cst)
149  { atomics::set(fvalue, _desired, mo); }
150  void store(_Tp _desired, mem_ord mo = std::memory_order_seq_cst) volatile
151  { atomics::set(fvalue, _desired, mo); }
152 
153  // load functions
154  _Tp load(mem_ord mo = std::memory_order_seq_cst) const
155  { return atomics::get(fvalue, mo); }
156  _Tp load(mem_ord mo = std::memory_order_seq_cst) const volatile
157  { return atomics::get(fvalue, mo); }
158 
159  // implicit conversion functions
160  operator _Tp() const { return this->load(); }
161  operator _Tp() const volatile { return this->load(); }
162 
163  operator base_type&() const { return fvalue; }
164 
165  // compare-and-swap functions
166  bool compare_exchange_weak(_Tp& _expected, _Tp _desired,
167  mem_ord _success, mem_ord _failure)
168  { return fvalue.compare_exchange_weak(_expected, _desired,
169  _success, _failure); }
170  bool compare_exchange_weak(_Tp& _expected, _Tp _desired,
171  mem_ord _success, mem_ord _failure) volatile
172  { return fvalue.compare_exchange_weak(_expected, _desired,
173  _success, _failure); }
174 
175  bool compare_exchange_weak(_Tp& _expected, _Tp _desired, mem_ord _order)
176  { return fvalue.compare_exchange_weak(_expected, _desired, _order); }
177  bool compare_exchange_weak(_Tp& _expected, _Tp _desired,
178  mem_ord _order) volatile
179  { return fvalue.compare_exchange_weak(_expected, _desired, _order); }
180 
181  bool compare_exchange_strong(_Tp& _expected, _Tp _desired,
182  mem_ord _success, mem_ord _failure)
183  { return fvalue.compare_exchange_weak(_expected, _desired,
184  _success, _failure); }
185  bool compare_exchange_strong(_Tp& _expected, _Tp _desired,
186  mem_ord _success, mem_ord _failure) volatile
187  { return fvalue.compare_exchange_weak(_expected, _desired,
188  _success, _failure); }
189 
190  bool compare_exchange_strong(_Tp& _expected, _Tp _desired, mem_ord _order)
191  { return fvalue.compare_exchange_weak(_expected, _desired, _order); }
192  bool compare_exchange_strong(_Tp& _expected, _Tp _desired,
193  mem_ord _order) volatile
194  { return fvalue.compare_exchange_weak(_expected, _desired, _order); }
195 
196  // value_type operators
197  G4atomic& operator+=(const value_type& rhs)
198  { atomics::increment(&fvalue, rhs, fMemOrder); return *this; }
199  G4atomic& operator-=(const value_type& rhs)
200  { atomics::decrement(&fvalue, rhs, fMemOrder); return *this; }
201  G4atomic& operator*=(const value_type& rhs)
202  { atomics::multiply(&fvalue, rhs, fMemOrder); return *this; }
203  G4atomic& operator/=(const value_type& rhs)
204  { atomics::divide(&fvalue, rhs, fMemOrder); return *this; }
205 
206  // atomic operators
207  G4atomic& operator+=(const G4atomic& rhs)
208  { atomics::increment(&fvalue, rhs.fvalue); return *this; }
209  G4atomic& operator-=(const G4atomic& rhs)
210  { atomics::decrement(&fvalue, rhs.fvalue); return *this; }
211  G4atomic& operator*=(const G4atomic& rhs)
212  { atomics::multiply(&fvalue, rhs.fvalue); return *this; }
213  G4atomic& operator/=(const G4atomic& rhs)
214  { atomics::divide(&fvalue, rhs.fvalue); return *this; }
215 
216  G4atomic& operator+=(const G4atomic& rhs) volatile
217  { atomics::increment(&fvalue, rhs.fvalue); return *this; }
218  G4atomic& operator-=(const G4atomic& rhs) volatile
219  { atomics::decrement(&fvalue, rhs.fvalue); return *this; }
220  G4atomic& operator*=(const G4atomic& rhs) volatile
221  { atomics::multiply(&fvalue, rhs.fvalue); return *this; }
222  G4atomic& operator/=(const G4atomic& rhs) volatile
223  { atomics::divide(&fvalue, rhs.fvalue); return *this; }
224 
225  // STL atomic operators
226  G4atomic& operator+=(const std::atomic<_Tp>& rhs)
227  { atomics::increment(&fvalue, rhs, fMemOrder); return *this; }
228  G4atomic& operator-=(const std::atomic<_Tp>& rhs)
229  { atomics::decrement(&fvalue, rhs, fMemOrder); return *this; }
230  G4atomic& operator*=(const std::atomic<_Tp>& rhs)
231  { atomics::multiply(&fvalue, rhs, fMemOrder); return *this; }
232  G4atomic& operator/=(const std::atomic<_Tp>& rhs)
233  { atomics::divide(&fvalue, rhs, fMemOrder); return *this; }
234 
235  G4atomic& operator+=(const std::atomic<_Tp>& rhs) volatile
236  { atomics::increment(&fvalue, rhs, fMemOrder); return *this; }
237  G4atomic& operator-=(const std::atomic<_Tp>& rhs) volatile
238  { atomics::decrement(&fvalue, rhs, fMemOrder); return *this; }
239  G4atomic& operator*=(const std::atomic<_Tp>& rhs) volatile
240  { atomics::multiply(&fvalue, rhs, fMemOrder); return *this; }
241  G4atomic& operator/=(const std::atomic<_Tp>& rhs) volatile
242  { atomics::divide(&fvalue, rhs, fMemOrder); return *this; }
243 
244  // increment operators
245  value_type operator++() { value_type _tmp = ++fvalue; return _tmp; }
246  value_type operator++(int)
247  { value_type _tmp = fvalue++; return _tmp; }
248 
249  value_type operator--() { value_type _tmp = --fvalue; return _tmp; }
250  value_type operator--(int)
251  { value_type _tmp = fvalue--; return _tmp; }
252 
253  protected:
254 
255  base_type fvalue;
256  mem_ord fMemOrder;
257 
258 };
259 
260 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
261 
262 #else // ! G4MULTITHREADED
263 
264 template <typename _Tp> using G4atomic = _Tp;
265 
266 #endif // G4MULTITHREADED
267 
268 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
269 
270 #endif // G4atomic_hh_