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

Applications | User Support | Publications | Collaboration