Plasma Engine  2.0
Loading...
Searching...
No Matches
AtomicUtils_win.h
1#ifdef PL_ATOMICUTLS_WIN_INL_H_INCLUDED
2# error "This file must not be included twice."
3#endif
4
5#define PL_ATOMICUTLS_WIN_INL_H_INCLUDED
6
7#include <intrin.h>
8
9PL_ALWAYS_INLINE plInt32 plAtomicUtils::Read(const plInt32& iSrc)
10{
11 return _InterlockedOr((long*)(&iSrc), 0);
12}
13
14PL_ALWAYS_INLINE plInt64 plAtomicUtils::Read(const plInt64& iSrc)
15{
16#if PL_ENABLED(PL_PLATFORM_32BIT)
17 plInt64 old;
18 do
19 {
20 old = iSrc;
21 } while (_InterlockedCompareExchange64(const_cast<plInt64*>(&iSrc), old, old) != old);
22 return old;
23#else
24 return _InterlockedOr64(const_cast<plInt64*>(&iSrc), 0);
25#endif
26}
27
28PL_ALWAYS_INLINE plInt32 plAtomicUtils::Increment(plInt32& ref_iDest)
29{
30 return _InterlockedIncrement(reinterpret_cast<long*>(&ref_iDest));
31}
32
33PL_ALWAYS_INLINE plInt64 plAtomicUtils::Increment(plInt64& ref_iDest)
34{
35#if PL_ENABLED(PL_PLATFORM_32BIT)
36 plInt64 old;
37 do
38 {
39 old = ref_iDest;
40 } while (_InterlockedCompareExchange64(&ref_iDest, old + 1, old) != old);
41 return old + 1;
42#else
43 return _InterlockedIncrement64(&ref_iDest);
44#endif
45}
46
47PL_ALWAYS_INLINE plInt32 plAtomicUtils::Decrement(plInt32& ref_iDest)
48{
49 return _InterlockedDecrement(reinterpret_cast<long*>(&ref_iDest));
50}
51
52PL_ALWAYS_INLINE plInt64 plAtomicUtils::Decrement(plInt64& ref_iDest)
53{
54#if PL_ENABLED(PL_PLATFORM_32BIT)
55 plInt64 old;
56 do
57 {
58 old = ref_iDest;
59 } while (_InterlockedCompareExchange64(&ref_iDest, old - 1, old) != old);
60 return old - 1;
61#else
62 return _InterlockedDecrement64(&ref_iDest);
63#endif
64}
65
66PL_ALWAYS_INLINE plInt32 plAtomicUtils::PostIncrement(plInt32& ref_iDest)
67{
68 return _InterlockedExchangeAdd(reinterpret_cast<long*>(&ref_iDest), 1);
69}
70
71PL_ALWAYS_INLINE plInt64 plAtomicUtils::PostIncrement(plInt64& ref_iDest)
72{
73#if PL_ENABLED(PL_PLATFORM_32BIT)
74 plInt64 old;
75 do
76 {
77 old = ref_iDest;
78 } while (_InterlockedCompareExchange64(&ref_iDest, old + 1, old) != old);
79 return old;
80#else
81 return _InterlockedExchangeAdd64(&ref_iDest, 1);
82#endif
83}
84
85PL_ALWAYS_INLINE plInt32 plAtomicUtils::PostDecrement(plInt32& ref_iDest)
86{
87 return _InterlockedExchangeAdd(reinterpret_cast<long*>(&ref_iDest), -1);
88}
89
90PL_ALWAYS_INLINE plInt64 plAtomicUtils::PostDecrement(plInt64& ref_iDest)
91{
92#if PL_ENABLED(PL_PLATFORM_32BIT)
93 plInt64 old;
94 do
95 {
96 old = ref_iDest;
97 } while (_InterlockedCompareExchange64(&ref_iDest, old - 1, old) != old);
98 return old;
99#else
100 return _InterlockedExchangeAdd64(&ref_iDest, -1);
101#endif
102}
103
104PL_ALWAYS_INLINE void plAtomicUtils::Add(plInt32& ref_iDest, plInt32 value)
105{
106 _InterlockedExchangeAdd(reinterpret_cast<long*>(&ref_iDest), value);
107}
108
109PL_ALWAYS_INLINE void plAtomicUtils::Add(plInt64& ref_iDest, plInt64 value)
110{
111#if PL_ENABLED(PL_PLATFORM_32BIT)
112 plInt64 old;
113 do
114 {
115 old = ref_iDest;
116 } while (_InterlockedCompareExchange64(&ref_iDest, old + value, old) != old);
117#else
118 _InterlockedExchangeAdd64(&ref_iDest, value);
119#endif
120}
121
122
123PL_ALWAYS_INLINE void plAtomicUtils::And(plInt32& ref_iDest, plInt32 value)
124{
125 _InterlockedAnd(reinterpret_cast<long*>(&ref_iDest), value);
126}
127
128PL_ALWAYS_INLINE void plAtomicUtils::And(plInt64& ref_iDest, plInt64 value)
129{
130#if PL_ENABLED(PL_PLATFORM_32BIT)
131 plInt64 old;
132 do
133 {
134 old = ref_iDest;
135 } while (_InterlockedCompareExchange64(&ref_iDest, old & value, old) != old);
136#else
137 _InterlockedAnd64(&ref_iDest, value);
138#endif
139}
140
141
142PL_ALWAYS_INLINE void plAtomicUtils::Or(plInt32& ref_iDest, plInt32 value)
143{
144 _InterlockedOr(reinterpret_cast<long*>(&ref_iDest), value);
145}
146
147PL_ALWAYS_INLINE void plAtomicUtils::Or(plInt64& ref_iDest, plInt64 value)
148{
149#if PL_ENABLED(PL_PLATFORM_32BIT)
150 plInt64 old;
151 do
152 {
153 old = ref_iDest;
154 } while (_InterlockedCompareExchange64(&ref_iDest, old | value, old) != old);
155#else
156 _InterlockedOr64(&ref_iDest, value);
157#endif
158}
159
160
161PL_ALWAYS_INLINE void plAtomicUtils::Xor(plInt32& ref_iDest, plInt32 value)
162{
163 _InterlockedXor(reinterpret_cast<long*>(&ref_iDest), value);
164}
165
166PL_ALWAYS_INLINE void plAtomicUtils::Xor(plInt64& ref_iDest, plInt64 value)
167{
168#if PL_ENABLED(PL_PLATFORM_32BIT)
169 plInt64 old;
170 do
171 {
172 old = ref_iDest;
173 } while (_InterlockedCompareExchange64(&ref_iDest, old ^ value, old) != old);
174#else
175 _InterlockedXor64(&ref_iDest, value);
176#endif
177}
178
179
180inline void plAtomicUtils::Min(plInt32& ref_iDest, plInt32 value)
181{
182 // tries to exchange dest with the new value as long as the oldValue is not what we expected
183 while (true)
184 {
185 plInt32 iOldValue = ref_iDest;
186 plInt32 iNewValue = value < iOldValue ? value : iOldValue; // do Min manually here, to break #include cycles
187
188 if (_InterlockedCompareExchange(reinterpret_cast<long*>(&ref_iDest), iNewValue, iOldValue) == iOldValue)
189 break;
190 }
191}
192
193inline void plAtomicUtils::Min(plInt64& ref_iDest, plInt64 value)
194{
195 // tries to exchange dest with the new value as long as the oldValue is not what we expected
196 while (true)
197 {
198 plInt64 iOldValue = ref_iDest;
199 plInt64 iNewValue = value < iOldValue ? value : iOldValue; // do Min manually here, to break #include cycles
200
201 if (_InterlockedCompareExchange64(&ref_iDest, iNewValue, iOldValue) == iOldValue)
202 break;
203 }
204}
205
206inline void plAtomicUtils::Max(plInt32& ref_iDest, plInt32 value)
207{
208 // tries to exchange dest with the new value as long as the oldValue is not what we expected
209 while (true)
210 {
211 plInt32 iOldValue = ref_iDest;
212 plInt32 iNewValue = iOldValue < value ? value : iOldValue; // do Max manually here, to break #include cycles
213
214 if (_InterlockedCompareExchange(reinterpret_cast<long*>(&ref_iDest), iNewValue, iOldValue) == iOldValue)
215 break;
216 }
217}
218
219inline void plAtomicUtils::Max(plInt64& ref_iDest, plInt64 value)
220{
221 // tries to exchange dest with the new value as long as the oldValue is not what we expected
222 while (true)
223 {
224 plInt64 iOldValue = ref_iDest;
225 plInt64 iNewValue = iOldValue < value ? value : iOldValue; // do Max manually here, to break #include cycles
226
227 if (_InterlockedCompareExchange64(&ref_iDest, iNewValue, iOldValue) == iOldValue)
228 break;
229 }
230}
231
232
233inline plInt32 plAtomicUtils::Set(plInt32& ref_iDest, plInt32 value)
234{
235 return _InterlockedExchange(reinterpret_cast<long*>(&ref_iDest), value);
236}
237
238PL_ALWAYS_INLINE plInt64 plAtomicUtils::Set(plInt64& ref_iDest, plInt64 value)
239{
240#if PL_ENABLED(PL_PLATFORM_32BIT)
241 plInt64 old;
242 do
243 {
244 old = ref_iDest;
245 } while (_InterlockedCompareExchange64(&ref_iDest, value, old) != old);
246 return old;
247#else
248 return _InterlockedExchange64(&ref_iDest, value);
249#endif
250}
251
252
253PL_ALWAYS_INLINE bool plAtomicUtils::TestAndSet(plInt32& ref_iDest, plInt32 iExpected, plInt32 value)
254{
255 return _InterlockedCompareExchange(reinterpret_cast<long*>(&ref_iDest), value, iExpected) == iExpected;
256}
257
258PL_ALWAYS_INLINE bool plAtomicUtils::TestAndSet(plInt64& ref_iDest, plInt64 iExpected, plInt64 value)
259{
260 return _InterlockedCompareExchange64(&ref_iDest, value, iExpected) == iExpected;
261}
262
263PL_ALWAYS_INLINE bool plAtomicUtils::TestAndSet(void** pDest, void* pExpected, void* value)
264{
265 return _InterlockedCompareExchangePointer(pDest, value, pExpected) == pExpected;
266}
267
268PL_ALWAYS_INLINE plInt32 plAtomicUtils::CompareAndSwap(plInt32& ref_iDest, plInt32 iExpected, plInt32 value)
269{
270 return _InterlockedCompareExchange(reinterpret_cast<long*>(&ref_iDest), value, iExpected);
271}
272
273PL_ALWAYS_INLINE plInt64 plAtomicUtils::CompareAndSwap(plInt64& ref_iDest, plInt64 iExpected, plInt64 value)
274{
275 return _InterlockedCompareExchange64(&ref_iDest, value, iExpected);
276}
static plInt32 Decrement(plInt32 &ref_iDest)
Decrements dest as an atomic operation and returns the new value.
Definition AtomicUtils_posix.h:31
static void Add(plInt32 &ref_iDest, plInt32 value)
Adds value to dest as an atomic operation.
Definition AtomicUtils_posix.h:62
static plInt32 CompareAndSwap(plInt32 &ref_iDest, plInt32 iExpected, plInt32 value)
If dest is equal to expected, this function sets dest to value. Otherwise dest will not be modified....
Definition AtomicUtils_posix.h:192
static void Or(plInt32 &ref_iDest, plInt32 value)
Performs an atomic bitwise OR on dest using value.
Definition AtomicUtils_posix.h:84
static plInt32 Read(const plInt32 &iSrc)
Returns src as an atomic operation and returns its value.
Definition AtomicUtils_posix.h:10
static void Min(plInt32 &ref_iDest, plInt32 value)
Performs an atomic min operation on dest using value.
Definition AtomicUtils_posix.h:106
static void And(plInt32 &ref_iDest, plInt32 value)
Performs an atomic bitwise AND on dest using value.
Definition AtomicUtils_posix.h:73
static void Xor(plInt32 &ref_iDest, plInt32 value)
Performs an atomic bitwise XOR on dest using value.
Definition AtomicUtils_posix.h:95
static plInt32 PostIncrement(plInt32 &ref_iDest)
Increments dest as an atomic operation and returns the old value.
Definition AtomicUtils_posix.h:41
static plInt32 Increment(plInt32 &ref_iDest)
Increments dest as an atomic operation and returns the new value.
Definition AtomicUtils_posix.h:20
static void Max(plInt32 &ref_iDest, plInt32 value)
Performs an atomic max operation on dest using value.
Definition AtomicUtils_posix.h:133
static plInt32 PostDecrement(plInt32 &ref_iDest)
Decrements dest as an atomic operation and returns the old value.
Definition AtomicUtils_posix.h:52
static plInt32 Set(plInt32 &ref_iDest, plInt32 value)
Sets dest to value as an atomic operation and returns the original value of dest.
Definition AtomicUtils_posix.h:160
static bool TestAndSet(plInt32 &ref_iDest, plInt32 iExpected, plInt32 value)
If dest is equal to expected, this function sets dest to value and returns true. Otherwise dest will ...
Definition AtomicUtils_posix.h:171