ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4atomic_defines.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4atomic_defines.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 //
35 //
36 //
37 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
38 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
39 
40 
41 #ifndef G4atomic_defines_hh_
42 #define G4atomic_defines_hh_
43 
44 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
45 
46 #ifdef G4MULTITHREADED
47 
48 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
49 
50 #include <functional>
51 #include <atomic>
52 
53 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
54 
55 namespace atomics
56 {
57  //------------------------------------------------------------------------//
58  namespace details
59  {
60  //--------------------------------------------------------------------//
61  template <typename _Tp>
62  using OpFunction = std::function<_Tp(const _Tp&, const _Tp&)>;
63  //--------------------------------------------------------------------//
64  template <typename _Tp>
65  inline void do_fetch_and_store(std::atomic<_Tp>* _atomic,
66  const _Tp& _value,
67  std::memory_order mem_odr)
68  {
69  _atomic->store(_value, mem_odr);
70  }
71  //--------------------------------------------------------------------//
72  template <typename _Tp>
73  inline void do_fetch_and_store(std::atomic<_Tp>* _atomic,
74  const std::atomic<_Tp>& _value,
75  std::memory_order mem_odr)
76  {
77  _atomic->store(_value.load(), mem_odr);
78  }
79  //--------------------------------------------------------------------//
80  template <typename _Tp>
81  inline void do_compare_and_swap(std::atomic<_Tp>* _atomic,
82  const _Tp& _value,
83  const OpFunction<_Tp>& _operator,
84  std::memory_order mem_odr)
85  {
86  _Tp _expected = _Tp();
87  do {
88  _expected = _atomic->load();
89  } while (!(_atomic->compare_exchange_weak(_expected,
90  _operator(_expected,
91  _value),
92  mem_odr)));
93  }
94  //--------------------------------------------------------------------//
95  template <typename _Tp>
96  inline void do_compare_and_swap(std::atomic<_Tp>* _atomic,
97  const std::atomic<_Tp>&
98  _atomic_value,
99  const OpFunction<_Tp>& _operator,
100  std::memory_order mem_odr)
101  {
102  _Tp _expected = _Tp();
103  do {
104  _expected = _atomic->load();
105  } while (!(_atomic->compare_exchange_weak(_expected,
106  _operator(_expected,
107  _atomic_value.load()),
108  mem_odr)));
109  }
110  //--------------------------------------------------------------------//
111  }
112  //------------------------------------------------------------------------//
113  // WITH ATOMIC TEMPLATE BASE TYPE AS SECOND PARAMETER
114  //------------------------------------------------------------------------//
115  template <typename T>
116  inline void set(std::atomic<T>* _atomic,
117  const T& _desired,
118  std::memory_order mem_odr
119  = std::memory_order_seq_cst)
120  {
121  details::do_compare_and_swap(_atomic,
122  _desired,
123  details::OpFunction<T>
124  ([](const T&, const T& y){return y;}),
125  mem_odr);
126  }
127  //------------------------------------------------------------------------//
128  template <typename T>
129  inline void set(std::atomic<T>& _atomic,
130  const T& _desired,
131  std::memory_order mem_odr
132  = std::memory_order_seq_cst)
133  {
134  set(&_atomic, _desired, mem_odr);
135  }
136  //------------------------------------------------------------------------//
137  template <typename T>
138  inline void increment(std::atomic<T>* _atomic,
139  const T& _increment,
140  std::memory_order mem_odr)
141  {
142  details::do_compare_and_swap(_atomic, _increment,
143  details::OpFunction<T>
144  ([](const T& x, const T& y){return x+y;}),
145  mem_odr);
146  }
147  //------------------------------------------------------------------------//
148  template <typename T>
149  inline void decrement(std::atomic<T>* _atomic, const T& _decrement,
150  std::memory_order mem_odr)
151  {
152  details::do_compare_and_swap(_atomic, _decrement,
153  details::OpFunction<T>
154  ([](const T& x, const T& y){return x-y;}),
155  mem_odr);
156  }
157  //------------------------------------------------------------------------//
158  template <typename T>
159  inline void multiply(std::atomic<T>* _atomic, const T& _factor,
160  std::memory_order mem_odr)
161  {
162  details::do_compare_and_swap(_atomic, _factor,
163  details::OpFunction<T>
164  ([](const T& x, const T& y){return x*y;}),
165  mem_odr);
166  }
167  //------------------------------------------------------------------------//
168  template <typename T>
169  inline void divide(std::atomic<T>* _atomic, const T& _factor,
170  std::memory_order mem_odr)
171  {
172  details::do_compare_and_swap(_atomic, _factor,
173  details::OpFunction<T>
174  ([](const T& x, const T& y){return x/y;}),
175  mem_odr);
176  }
177  //------------------------------------------------------------------------//
178  // WITH ATOMICS AS SECOND PARAMETER
179  //------------------------------------------------------------------------//
180  template <typename T>
181  inline void set(std::atomic<T>* _atomic,
182  const std::atomic<T>& _atomic_desired,
183  std::memory_order mem_odr
184  = std::memory_order_seq_cst)
185  {
186  //details::do_fetch_and_store(_atomic, _desired);
187  details::do_compare_and_swap(_atomic, _atomic_desired,
188  details::OpFunction<T>
189  ([](const T&, const T& y){return y;}),
190  mem_odr);
191  }
192  //------------------------------------------------------------------------//
193  template <typename T>
194  inline void set(std::atomic<T>& _atomic,
195  const std::atomic<T>& _atomic_desired,
196  std::memory_order mem_odr)
197  {
198  set(&_atomic, _atomic_desired, mem_odr);
199  }
200  //------------------------------------------------------------------------//
201  template <typename T>
202  inline void increment(std::atomic<T>* _atomic,
203  const std::atomic<T>& _atomic_increment,
204  std::memory_order mem_odr)
205  {
206  details::do_compare_and_swap(_atomic, _atomic_increment,
207  details::OpFunction<T>
208  ([](const T& x, const T& y){return x+y;}),
209  mem_odr);
210  }
211  //------------------------------------------------------------------------//
212  template <typename T>
213  inline void decrement(std::atomic<T>* _atomic,
214  const std::atomic<T>& _atomic_decrement,
215  std::memory_order mem_odr)
216  {
217  details::do_compare_and_swap(_atomic, _atomic_decrement,
218  details::OpFunction<T>
219  ([](const T& x, const T& y){return x-y;}),
220  mem_odr);
221  }
222  //------------------------------------------------------------------------//
223  template <typename T>
224  inline void multiply(std::atomic<T>* _atomic,
225  const std::atomic<T>& _atomic_factor,
226  std::memory_order mem_odr)
227  {
228  details::do_compare_and_swap(_atomic, _atomic_factor,
229  details::OpFunction<T>
230  ([](const T& x, const T& y){return x*y;}),
231  mem_odr);
232  }
233  //------------------------------------------------------------------------//
234  template <typename T>
235  inline void divide(std::atomic<T>* _atomic,
236  const std::atomic<T>& _atomic_factor,
237  std::memory_order mem_odr)
238  {
239  details::do_compare_and_swap(_atomic, _atomic_factor,
240  details::OpFunction<T>
241  ([](const T& x, const T& y){return x/y;}),
242  mem_odr);
243  }
244 
245  //------------------------------------------------------------------------//
246  // STANDARD OVERLOAD //
247  //------------------------------------------------------------------------//
248  template <typename T>
249  inline void set(T* _non_atomic, const T& _desired)
250  {
251  *_non_atomic = _desired;
252  }
253  //------------------------------------------------------------------------//
254  template <typename T>
255  inline void set(T& _non_atomic, const T& _desired)
256  {
257  set(&_non_atomic, _desired);
258  }
259  //------------------------------------------------------------------------//
260  // STL PAIR OVERLOAD //
261  //------------------------------------------------------------------------//
262  //
263  //------------------------------------------------------------------------//
264  // WITH ATOMIC TEMPLATE TYPE AS SECOND PARAMETER
265  //------------------------------------------------------------------------//
266  template <typename T, typename U>
267  inline void set(std::pair<std::atomic<T>,
268  std::atomic<U> >* _atomic,
269  const std::pair<T, U>& _desired)
270  {
271  set(&_atomic->first, _desired.first);
272  set(&_atomic->second, _desired.second);
273  }
274  //------------------------------------------------------------------------//
275  template <typename T, typename U>
276  inline void set(std::pair<std::atomic<T>,
277  std::atomic<U> >& _atomic,
278  const std::pair<T, U>& _desired)
279  {
280  set(&_atomic, _desired);
281  }
282  //------------------------------------------------------------------------//
283  template <typename T, typename U>
284  inline void increment(std::pair<std::atomic<T>,
285  std::atomic<U> >* _atomic,
286  const std::pair<T, U>& _increment)
287  {
288  increment(&_atomic->first, _increment.first);
289  increment(&_atomic->second, _increment.second);
290  }
291  //------------------------------------------------------------------------//
292  template <typename T, typename U>
293  inline void decrement(std::pair<std::atomic<T>,
294  std::atomic<U> >* _atomic,
295  const std::pair<T, U>& _decrement)
296  {
297  decrement(&_atomic->first, _decrement.first);
298  decrement(&_atomic->second, _decrement.second);
299  }
300  //------------------------------------------------------------------------//
301  template <typename T, typename U>
302  inline void multiply(std::pair<std::atomic<T>,
303  std::atomic<U> >* _atomic,
304  const std::pair<T, U>& _factor)
305  {
306  multiply(&_atomic->first, _factor.first);
307  multiply(&_atomic->second, _factor.second);
308  }
309  //------------------------------------------------------------------------//
310  template <typename T, typename U>
311  inline void divide(std::pair<std::atomic<T>,
312  std::atomic<U> >* _atomic,
313  const std::pair<T, U>& _factor)
314  {
315  divide(&_atomic->first, _factor.first);
316  divide(&_atomic->second, _factor.second);
317  }
318  //------------------------------------------------------------------------//
319  // WITH ATOMICS AS SECOND PARAMETER
320  //------------------------------------------------------------------------//
321  template <typename T, typename U>
322  inline void set(std::pair<std::atomic<T>,
323  std::atomic<U> >* _atomic,
324  const std::pair<std::atomic<T>,
325  std::atomic<U> >& _desired)
326  {
327  set(&_atomic->first, _desired.first);
328  set(&_atomic->second, _desired.second);
329  }
330  //------------------------------------------------------------------------//
331  template <typename T, typename U>
332  inline void set(std::pair<std::atomic<T>,
333  std::atomic<U> >& _atomic,
334  const std::pair<std::atomic<T>,
335  std::atomic<U> >& _desired)
336  {
337  set(&_atomic, _desired);
338  }
339  //------------------------------------------------------------------------//
340  template <typename T, typename U>
341  inline void increment(std::pair<std::atomic<T>,
342  std::atomic<U> >* _atomic,
343  const std::pair<std::atomic<T>,
344  std::atomic<U> >& _increment)
345  {
346  increment(&_atomic->first, _increment.first);
347  increment(&_atomic->second, _increment.second);
348  }
349  //------------------------------------------------------------------------//
350  template <typename T, typename U>
351  inline void decrement(std::pair<std::atomic<T>,
352  std::atomic<U> >* _atomic,
353  const std::pair<std::atomic<T>,
354  std::atomic<U> >& _decrement)
355  {
356  decrement(&_atomic->first, _decrement.first);
357  decrement(&_atomic->second, _decrement.second);
358  }
359  //------------------------------------------------------------------------//
360  template <typename T, typename U>
361  inline void multiply(std::pair<std::atomic<T>,
362  std::atomic<U> >* _atomic,
363  const std::pair<std::atomic<T>,
364  std::atomic<U> >& _factor)
365  {
366  multiply(&_atomic->first, _factor.first);
367  multiply(&_atomic->second, _factor.second);
368  }
369  //------------------------------------------------------------------------//
370  template <typename T, typename U>
371  inline void divide(std::pair<std::atomic<T>,
372  std::atomic<U> >* _atomic,
373  const std::pair<std::atomic<T>,
374  std::atomic<U> >& _factor)
375  {
376  divide(&_atomic->first, _factor.first);
377  divide(&_atomic->second, _factor.second);
378  }
379  //------------------------------------------------------------------------//
380 
381 
382  //------------------------------------------------------------------------//
383  template <typename T>
384  inline T get(const T& _non_atomic)
385  {
386  return _non_atomic;
387  }
388  //------------------------------------------------------------------------//
389  template <typename T>
390  inline T get(const T& _non_atomic, std::memory_order)
391  {
392  return _non_atomic;
393  }
394  //------------------------------------------------------------------------//
395  template <typename T>
396  inline T get(const std::atomic<T>& _atomic)
397  {
398  return _atomic.load();
399  }
400  //------------------------------------------------------------------------//
401  template <typename T>
402  inline T get(const std::atomic<T>& _atomic,
403  std::memory_order mem_odr)
404  {
405  return _atomic.load(mem_odr);
406  }
407  //------------------------------------------------------------------------//
408  template <typename T, typename U>
409  inline std::pair<T, U> get(const std::pair<std::atomic<T>,
410  std::atomic<U> >& _atomic)
411  {
412  return std::pair<T, U>(get(_atomic.first), get(_atomic.second));
413  }
414  //------------------------------------------------------------------------//
415  template <typename T, typename U>
416  inline std::pair<T, U> get(const std::pair<std::atomic<T>,
417  std::atomic<U> >& _atomic,
418  std::memory_order mem_odr)
419  {
420  return std::pair<T, U>(get(_atomic.first, mem_odr),
421  get(_atomic.second, mem_odr));
422  }
423  //------------------------------------------------------------------------//
424 
425 
426 
427  //------------------------------------------------------------------------//
428  // for plain old data (POD) and pairs (e.g. std::pair<atomic<T>, atomic<U>>)
429  template <typename _Tp_base, typename _Tp_atom>
430  inline _Tp_base base(const _Tp_atom& _atomic)
431  {
432  return get(_atomic);
433  }
434  //------------------------------------------------------------------------//
435 
436 } // namespace atomics
437 
438 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
439 
440 #endif // G4MULTITHREADED
441 
442 #endif // atomic_typedefs_hh_