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 ( UT Library, C++)
7  *
8  * COMMENTS: Thread-safe operations on 32-bit 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  const;
55  /// Atomically retrieve value. Same as calling load().
56  operator T() const;
57 
58  /// Forced RELAXED memory load
59  /// GCC has trouble inlining so we pull the definition up here.
61 #ifdef WIN32
62  { return load(SYS_MEMORY_ORDER_RELAXED); }
63 #else
64  { return *static_cast<const volatile T *>(&myValue); }
65 #endif
66 
69 
70 private:
71  T myValue;
72 
73 private:
74  // Prohibited operators
75  SYS_AtomicInt(const SYS_AtomicInt &) = default;
76  SYS_AtomicInt &operator=(const SYS_AtomicInt &) = default;
77 };
78 
81 
82 #ifdef AMD64
84 #else
86 #endif
87 
88 template <typename T>
91 {
92  return SYS_AtomicImpl::test_and_set(&myValue, val);
93 }
94 
95 template <typename T>
98 {
99  return SYS_AtomicImpl::test_and_add(&myValue, val);
100 }
101 
102 template <typename T>
105 {
106  return SYS_AtomicImpl::test_and_add(&myValue, val) + val;
107 }
108 
109 template <typename T>
112 {
113  while (true)
114  {
115  T me = myValue;
116  if (val > me)
117  {
118  if (me == compare_swap(me, val))
119  return;
120  }
121  else
122  {
123  return;
124  }
125  }
126 }
127 
128 template <typename T>
130 SYS_AtomicInt<T>::compare_swap(T expected, T desired)
131 {
132  return SYS_AtomicImpl::compare_and_swap(&myValue, expected, desired);
133 }
134 
135 /// Next two methods intentionally not marked as volatile as this would cause
136 /// &myValue to evaluate to a pointer to a volatile myValue and that has
137 /// implications on MSVC2005+ beyond the C++ spec.
138 ///
139 /// This shouldn't be a problem unless somebody needs a volatile instance of
140 /// SYS_AtomicInt<T>.
141 template <typename T>
144 {
145  SYS_AtomicImpl::store(&myValue, val, order);
146 }
147 
148 template <typename T>
151 {
152  return SYS_AtomicImpl::load(&myValue, order);
153 }
154 
155 template <typename T>
158 {
159  return load();
160 }
161 
162 #endif
163 
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:79
void store(T val, SYS_MemoryOrder order=SYS_MEMORY_ORDER_SEQ_CST)
T exchange(T val)
Definition: SYS_AtomicInt.h:90
SYS_AtomicInt(SYS_EmptyConstructor)
Definition: SYS_AtomicInt.h:28
T exchangeAdd(T val)
Definition: SYS_AtomicInt.h:97
SYS_MemoryOrder
void maximum(T val)
Atomically set myValue to the maximum of val and myValue.
SYS_EmptyConstructor
Definition: SYS_Types.h:414
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:80
T test_and_add(T *addr, T val)
Any reordering the compiler or hardware chooses to do is okay.
GLsizei const GLfloat * value
Definition: glcorearb.h:823
SYS_AtomicInt< int32 > SYS_AtomicCounter
Definition: SYS_AtomicInt.h:85
GLuint GLfloat * val
Definition: glcorearb.h:1607
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:67
SYS_FORCE_INLINE T relaxedLoad() const
Definition: SYS_AtomicInt.h:60