1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
4 
5 
6 /////////////////////////////////////////////////////////////////////////
7 /// @file   atomic.h
8 ///
9 /// @brief  Wrappers and utilities for atomics.
10 /////////////////////////////////////////////////////////////////////////
11 
12 #pragma once
13 
14 #include <OpenImageIO/oiioversion.h>
15 #include <OpenImageIO/platform.h>
16 
17 #include <atomic>
18 #define OIIO_USE_STDATOMIC 1
19 
20 
21 
22 OIIO_NAMESPACE_BEGIN
23 
24 using std::atomic;
25 typedef atomic<int> atomic_int;
26 typedef atomic<long long> atomic_ll;
27 
28 
29 
30 /// Atomically set avar to the minimum of its current value and bval.
31 template<typename T>
32 OIIO_FORCEINLINE void
atomic_min(atomic<T> & avar,const T & bval)33 atomic_min(atomic<T>& avar, const T& bval)
34 {
35     do {
36         T a = avar.load();
37         if (a <= bval || avar.compare_exchange_weak(a, bval))
38             break;
39     } while (true);
40 }
41 
42 
43 /// Atomically set avar to the maximum of its current value and bval.
44 template<typename T>
45 OIIO_FORCEINLINE void
atomic_max(atomic<T> & avar,const T & bval)46 atomic_max(atomic<T>& avar, const T& bval)
47 {
48     do {
49         T a = avar.load();
50         if (a >= bval || avar.compare_exchange_weak(a, bval))
51             break;
52     } while (true);
53 }
54 
55 
56 
57 // Add atomically to a float and return the original value.
58 OIIO_FORCEINLINE float
atomic_fetch_add(atomic<float> & a,float f)59 atomic_fetch_add(atomic<float>& a, float f)
60 {
61     do {
62         float oldval = a.load();
63         float newval = oldval + f;
64         if (a.compare_exchange_weak(oldval, newval))
65             return oldval;
66     } while (true);
67 }
68 
69 
70 // Add atomically to a double and return the original value.
71 OIIO_FORCEINLINE double
atomic_fetch_add(atomic<double> & a,double f)72 atomic_fetch_add(atomic<double>& a, double f)
73 {
74     do {
75         double oldval = a.load();
76         double newval = oldval + f;
77         if (a.compare_exchange_weak(oldval, newval))
78             return oldval;
79     } while (true);
80 }
81 
82 
83 OIIO_NAMESPACE_END
84