HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SYS_AtomicInt.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: SYS_AtomicInt.h (SYS Library, C++)
7  *
8  * COMMENTS: Thread-safe operations on integers
9  */
10 
11 #ifndef __SYS_AtomicInt__
12 #define __SYS_AtomicInt__
13 
14 #include "SYS_Types.h"
15 #include "SYS_MemoryOrder.h"
16 #include "SYS_AtomicImpl.h"
17 #include "SYS_TypeDecorate.h"
18 
19 #include <atomic>
20 
21 template <typename T>
23 {
24 public:
25  explicit SYS_AtomicInt(T value = 0) : myValue(value) {}
26 
27  /// An empty constructor. This will initialize the value with garbage,
28  /// unless used as a static object (in which case it will be guaranteed
29  /// by the C++ standard to be initialized to zero). Only use if required
30  /// to be set prior to other, dependent statically initialized objects.
32 
33  /// Atomically assigns val to myValue, returning the prior value of
34  /// myValue.
35  inline T exchange(T val);
36 
37  /// Atomically adds val to myValue, returning the prior value of
38  /// myValue.
39  inline T exchangeAdd(T val);
40 
41  /// Atomically adds val to myValue, returning the new value of myValue.
42  inline T add(T val);
43 
44  /// Atomically adds val to myValue, returning the new value of myValue.
45  inline T add(T val, SYS_MemoryOrder order);
46 
47  /// Atomically set myValue to the maximum of val and myValue. Returns the
48  /// last known maximal value.
49  inline T maximum(T val);
50 
51  /// Atomically set myValue to the minimum of val and myValue. Returns the
52  /// last known minimal value.
53  inline T minimum(T val);
54 
55  /// Atomically compares (myValue == expected), and if true, replaces
56  /// myValue with desired. Returns the prior value.
57  inline T compare_swap(T expected, T desired);
58 
59  inline bool compareExchangeStrong(
60  T &expected,
61  T desired,
64 
65  inline bool compareExchangeWeak(
66  T &expected,
67  T desired,
70 
71  /// @pre The supplied order must be one of [RELAXED, STORE, SEQ_CST].
73 
74  /// @pre The supplied order must be one of [RELAXED, LOAD, SEQ_CST].
76 
77  /// Forced RELAXED memory load
78  /// GCC has trouble inlining so we pull the definition up here.
80 
82 
83 private:
84  std::atomic<T> myValue;
85 
86 private:
87  // Prohibited operators
88  SYS_AtomicInt(const SYS_AtomicInt &) = default;
89  SYS_AtomicInt &operator=(const SYS_AtomicInt &) = default;
90  /// WARNING: DO NOT ADD THIS BACK! It was atomic, and nobody expected that,
91  /// so it ended up slowing down many things, including every
92  /// string attribute read.
93  explicit operator T() const;
94 };
95 
98 
99 #if defined(AMD64) || defined(ARM64)
101 #else
103 #endif
104 
105 template <typename T>
107 
108 template <typename T>
111 {
112  return myValue.exchange(val);
113 }
114 
115 template <typename T>
118 {
119  return myValue.fetch_add(val);
120 }
121 
122 template <typename T>
125 {
126  return (myValue += val);
127 }
128 
129 template <typename T>
132 {
133  return myValue.fetch_add(val, order) + val;
134 }
135 
136 template <typename T>
139 {
140  T me = relaxedLoad();
141 
142  do
143  {
144  if (me > val)
145  break;
146  }
147  while (!compareExchangeWeak(me, val));
148 
149  return me;
150 }
151 
152 template <typename T>
155 {
156  T me = relaxedLoad();
157 
158  do
159  {
160  if (me < val)
161  break;
162  }
163  while (!compareExchangeWeak(me, val));
164 
165  return me;
166 }
167 
168 template <typename T>
170 SYS_AtomicInt<T>::compare_swap(T expected, T desired)
171 {
172  compareExchangeStrong(expected, desired);
173  return expected;
174 }
175 
176 template <typename T>
179  T &expected,
180  T desired,
181  SYS_MemoryOrder success,
182  SYS_MemoryOrder failure)
183 {
184  return myValue.compare_exchange_strong(
185  expected, desired, success, failure);
186 }
187 
188 template <typename T>
191  T &expected,
192  T desired,
193  SYS_MemoryOrder success,
194  SYS_MemoryOrder failure)
195 {
196  return myValue.compare_exchange_weak(
197  expected, desired, success, failure);
198 }
199 
200 /// Next two methods intentionally not marked as volatile as this would cause
201 /// &myValue to evaluate to a pointer to a volatile myValue and that has
202 /// implications on MSVC2005+ beyond the C++ spec.
203 ///
204 /// This shouldn't be a problem unless somebody needs a volatile instance of
205 /// SYS_AtomicInt<T>.
206 template <typename T>
209 {
210  myValue.store(val, order);
211 }
212 
213 template <typename T>
216 {
217  return myValue.load(order);
218 }
219 
220 template <typename T>
223 {
224  return myValue.load(std::memory_order_relaxed);
225 }
226 
227 template <typename T>
230 {
231  myValue.store(val, std::memory_order_relaxed);
232 };
233 
234 #endif
#define SYS_DECLARE_LEGACY_TR_TEMPLATE(...)
Version for class template.
GLsizei const GLfloat * value
Definition: glcorearb.h:824
constexpr SYS_MemoryOrder SYS_MEMORY_ORDER_SEQ_CST
SYS_FORCE_INLINE void relaxedStore(T val)
SYS_AtomicInt(T value=0)
Definition: SYS_AtomicInt.h:25
SYS_AtomicInt< int32 > SYS_AtomicInt32
Definition: SYS_AtomicInt.h:96
void store(T val, SYS_MemoryOrder order=SYS_MEMORY_ORDER_SEQ_CST)
T exchange(T val)
SYS_AtomicInt(SYS_EmptyConstructor)
Definition: SYS_AtomicInt.h:31
T exchangeAdd(T val)
bool compareExchangeStrong(T &expected, T desired, SYS_MemoryOrder success=SYS_MEMORY_ORDER_SEQ_CST, SYS_MemoryOrder failure=SYS_MEMORY_ORDER_SEQ_CST)
SYS_EmptyConstructor
Definition: SYS_Types.h:436
T load(SYS_MemoryOrder order=SYS_MEMORY_ORDER_SEQ_CST) const
bool compareExchangeWeak(T &expected, T desired, SYS_MemoryOrder success=SYS_MEMORY_ORDER_SEQ_CST, SYS_MemoryOrder failure=SYS_MEMORY_ORDER_SEQ_CST)
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
#define SYS_ATOMIC_INLINE
T compare_swap(T expected, T desired)
SYS_AtomicInt< int64 > SYS_AtomicInt64
Definition: SYS_AtomicInt.h:97
GLdouble GLdouble GLint GLint order
Definition: glad.h:2676
SYS_FORCE_INLINE T relaxedLoad() const
T minimum(T val)
SYS_AtomicInt< int32 > SYS_AtomicCounter
T maximum(T val)
VULKAN_HPP_CONSTEXPR_14 VULKAN_HPP_INLINE T exchange(T &obj, U &&newValue)
Definition: vulkan_raii.hpp:25
GLuint GLfloat * val
Definition: glcorearb.h:1608
T add(T val)
Atomically adds val to myValue, returning the new value of myValue.
std::memory_order SYS_MemoryOrder