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 
44  /// Atomically compares (myValue == expected), and if true, replaces
45  /// myValue with desired. Returns prior myValue.
46  inline T compare_swap(T expected, T desired);
47 
48  /// @pre The supplied order must be one of [RELAXED, STORE, SEQ_CST].
49  inline void store(T val,
51 
52  /// @pre The supplied order must be one of [RELAXED, LOAD, SEQ_CST].
54 
55  /// Forced RELAXED memory load
56  /// GCC has trouble inlining so we pull the definition up here.
58 #ifdef WIN32
59  { return load(SYS_MEMORY_ORDER_RELAXED); }
60 #else
61  { return *static_cast<const volatile T *>(&myValue); }
62 #endif
63 
66 
67 private:
68  T myValue;
69 
70 private:
71  // Prohibited operators
72  SYS_AtomicInt(const SYS_AtomicInt &) = default;
73  SYS_AtomicInt &operator=(const SYS_AtomicInt &) = default;
74  /// WARNING: DO NOT ADD THIS BACK! It was atomic, and nobody expected that,
75  /// so it ended up slowing down many things, including every
76  /// string attribute read.
77  explicit operator T() const;
78 };
79 
82 
83 #ifdef AMD64
85 #else
87 #endif
88 
89 template <typename T>
92 {
93  return SYS_AtomicImpl::test_and_set(&myValue, val);
94 }
95 
96 template <typename T>
99 {
100  return SYS_AtomicImpl::test_and_add(&myValue, val);
101 }
102 
103 template <typename T>
106 {
107  return SYS_AtomicImpl::test_and_add(&myValue, val) + val;
108 }
109 
110 template <typename T>
113 {
114  while (true)
115  {
116  T me = myValue;
117  if (val > me)
118  {
119  if (me == compare_swap(me, val))
120  return;
121  }
122  else
123  {
124  return;
125  }
126  }
127 }
128 
129 template <typename T>
131 SYS_AtomicInt<T>::compare_swap(T expected, T desired)
132 {
133  return SYS_AtomicImpl::compare_and_swap(&myValue, expected, desired);
134 }
135 
136 /// Next two methods intentionally not marked as volatile as this would cause
137 /// &myValue to evaluate to a pointer to a volatile myValue and that has
138 /// implications on MSVC2005+ beyond the C++ spec.
139 ///
140 /// This shouldn't be a problem unless somebody needs a volatile instance of
141 /// SYS_AtomicInt<T>.
142 template <typename T>
145 {
146  SYS_AtomicImpl::store(&myValue, val, order);
147 }
148 
149 template <typename T>
152 {
153  return SYS_AtomicImpl::load(&myValue, order);
154 }
155 
156 
157 #endif
158 
T compare_and_swap(volatile T *addr, T oldval, T newval)
GLuint const GLfloat * val
Definition: glew.h:2794
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:80
void store(T val, SYS_MemoryOrder order=SYS_MEMORY_ORDER_SEQ_CST)
T exchange(T val)
Definition: SYS_AtomicInt.h:91
SYS_AtomicInt(SYS_EmptyConstructor)
Definition: SYS_AtomicInt.h:28
T exchangeAdd(T val)
Definition: SYS_AtomicInt.h:98
SYS_MemoryOrder
void maximum(T val)
Atomically set myValue to the maximum of val and myValue.
SYS_EmptyConstructor
Definition: SYS_Types.h:420
GLuint GLdouble GLdouble GLint GLint order
Definition: glew.h:3446
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:81
T test_and_add(T *addr, T val)
Any reordering the compiler or hardware chooses to do is okay.
SYS_AtomicInt< int32 > SYS_AtomicCounter
Definition: SYS_AtomicInt.h:86
T add(T val)
Atomically adds val to myValue, returning the new value of myValue.
#define const
Definition: zconf.h:214
SYS_FORCE_INLINE void relaxedStore(T val)
Definition: SYS_AtomicInt.h:64
GLsizei const GLfloat * value
Definition: glew.h:1849
SYS_FORCE_INLINE T relaxedLoad() const
Definition: SYS_AtomicInt.h:57