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 
18 template <typename T>
20 {
21 public:
22  explicit SYS_AtomicInt(T value = 0) : myValue(value) {}
23 
24  /// An empty constructor. This will initialize the value with garbage,
25  /// unless used as a static object (in which case it will be guaranteed
26  /// by the C++ standard to be initialized to zero). Only use if required
27  /// to be set prior to other, dependent statically initialized objects.
29 
30  /// Atomically assigns val to myValue, returning the prior value of
31  /// myValue.
32  inline T exchange(T val);
33 
34  /// Atomically adds val to myValue, returning the prior value of
35  /// myValue.
36  inline T exchangeAdd(T val);
37 
38  /// Atomically adds val to myValue, returning the new value of myValue.
39  inline T add(T val);
40 
41  /// Atomically set myValue to the maximum of val and myValue.
42  inline void maximum(T val);
43  /// Atomically set myValue to the minimum of val and myValue.
44  inline void minimum(T val);
45 
46  /// Atomically compares (myValue == expected), and if true, replaces
47  /// myValue with desired. Returns prior myValue.
48  inline T compare_swap(T expected, T desired);
49 
50  /// @pre The supplied order must be one of [RELAXED, STORE, SEQ_CST].
51  inline void store(T val,
53 
54  /// @pre The supplied order must be one of [RELAXED, LOAD, SEQ_CST].
56 
57  /// Forced RELAXED memory load
58  /// GCC has trouble inlining so we pull the definition up here.
60 #ifdef WIN32
61  { return load(SYS_MEMORY_ORDER_RELAXED); }
62 #else
63  { return *static_cast<const volatile T *>(&myValue); }
64 #endif
65 
68 
69 private:
70  T myValue;
71 
72 private:
73  // Prohibited operators
74  SYS_AtomicInt(const SYS_AtomicInt &) = default;
75  SYS_AtomicInt &operator=(const SYS_AtomicInt &) = default;
76  /// WARNING: DO NOT ADD THIS BACK! It was atomic, and nobody expected that,
77  /// so it ended up slowing down many things, including every
78  /// string attribute read.
79  explicit operator T() const;
80 };
81 
84 
85 #if defined(AMD64) || defined(ARM64)
87 #else
89 #endif
90 
91 template <typename T>
94 {
95  return SYS_AtomicImpl::test_and_set(&myValue, val);
96 }
97 
98 template <typename T>
101 {
102  return SYS_AtomicImpl::test_and_add(&myValue, val);
103 }
104 
105 template <typename T>
108 {
109  return SYS_AtomicImpl::test_and_add(&myValue, val) + val;
110 }
111 
112 template <typename T>
115 {
116  while (true)
117  {
118  T me = myValue;
119  if (val > me)
120  {
121  if (me == compare_swap(me, val))
122  return;
123  }
124  else
125  {
126  return;
127  }
128  }
129 }
130 
131 template <typename T>
134 {
135  while (true)
136  {
137  T me = myValue;
138  if (val < me)
139  {
140  if (me == compare_swap(me, val))
141  return;
142  }
143  else
144  {
145  return;
146  }
147  }
148 }
149 
150 template <typename T>
152 SYS_AtomicInt<T>::compare_swap(T expected, T desired)
153 {
154  return SYS_AtomicImpl::compare_and_swap(&myValue, expected, desired);
155 }
156 
157 /// Next two methods intentionally not marked as volatile as this would cause
158 /// &myValue to evaluate to a pointer to a volatile myValue and that has
159 /// implications on MSVC2005+ beyond the C++ spec.
160 ///
161 /// This shouldn't be a problem unless somebody needs a volatile instance of
162 /// SYS_AtomicInt<T>.
163 template <typename T>
166 {
167  SYS_AtomicImpl::store(&myValue, val, order);
168 }
169 
170 template <typename T>
173 {
174  return SYS_AtomicImpl::load(&myValue, order);
175 }
176 
177 
178 #endif
179 
GLuint GLdouble GLdouble GLint GLint order
Definition: glew.h:3460
T compare_and_swap(volatile T *addr, T oldval, T newval)
SYS_AtomicInt(T value=0)
Definition: SYS_AtomicInt.h:22
T test_and_set(T *addr, T val)
SYS_AtomicInt< int32 > SYS_AtomicInt32
Definition: SYS_AtomicInt.h:82
void store(T val, SYS_MemoryOrder order=SYS_MEMORY_ORDER_SEQ_CST)
T exchange(T val)
Definition: SYS_AtomicInt.h:93
SYS_AtomicInt(SYS_EmptyConstructor)
Definition: SYS_AtomicInt.h:28
T exchangeAdd(T val)
SYS_MemoryOrder
void maximum(T val)
Atomically set myValue to the maximum of val and myValue.
SYS_EmptyConstructor
Definition: SYS_Types.h:435
T load(SYS_MemoryOrder order=SYS_MEMORY_ORDER_SEQ_CST) const
#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:83
T test_and_add(T *addr, T val)
Any reordering the compiler or hardware chooses to do is okay.
GLuint GLfloat * val
Definition: glcorearb.h:1608
SYS_AtomicInt< int32 > SYS_AtomicCounter
Definition: SYS_AtomicInt.h:88
T add(T val)
Atomically adds val to myValue, returning the new value of myValue.
Definition: core.h:1131
#define const
Definition: zconf.h:214
SYS_FORCE_INLINE void relaxedStore(T val)
Definition: SYS_AtomicInt.h:66
void minimum(T val)
Atomically set myValue to the minimum of val and myValue.
SYS_FORCE_INLINE T relaxedLoad() const
Definition: SYS_AtomicInt.h:59