29 #ifndef JUCE_ATOMIC_H_INCLUDED
30 #define JUCE_ATOMIC_H_INCLUDED
40 template <
typename Type>
52 :
value (initialValue)
156 template <
typename Dest,
typename Source>
157 static inline Dest castTo (Source
value)
noexcept {
union { Dest d; Source s; } u; u.s =
value;
return u.d; }
168 template <
typename ValueType>
169 inline ValueType negateValue (ValueType n)
noexcept
171 return sizeof (ValueType) == 1 ? (ValueType) -(
signed char) n
172 : (
sizeof (ValueType) == 2 ? (ValueType) -(
short) n
173 : (
sizeof (ValueType) == 4 ? (ValueType) -(int) n
174 : ((ValueType) -(
int64) n)));
178 template <
typename Po
interType>
179 inline PointerType* negateValue (PointerType* n)
noexcept
181 return reinterpret_cast <PointerType*
> (-
reinterpret_cast <pointer_sized_int> (n));
190 #if JUCE_MAC && (JUCE_PPC || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
191 #define JUCE_ATOMICS_MAC_LEGACY 1 // Older OSX builds using gcc4.1 or earlier
193 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
194 #define JUCE_MAC_ATOMICS_VOLATILE
196 #define JUCE_MAC_ATOMICS_VOLATILE volatile
201 template <
typename Type>
static Type OSAtomicAdd64Barrier (Type b, JUCE_MAC_ATOMICS_VOLATILE Type* a)
noexcept {
jassertfalse;
return *a += b; }
202 template <
typename Type>
static Type OSAtomicIncrement64Barrier (JUCE_MAC_ATOMICS_VOLATILE Type* a)
noexcept {
jassertfalse;
return ++*a; }
203 template <
typename Type>
static Type OSAtomicDecrement64Barrier (JUCE_MAC_ATOMICS_VOLATILE Type* a)
noexcept {
jassertfalse;
return --*a; }
204 template <
typename Type>
static bool OSAtomicCompareAndSwap64Barrier (Type old, Type newValue, JUCE_MAC_ATOMICS_VOLATILE Type* value)
noexcept
205 {
jassertfalse;
if (old == *value) { *value = newValue;
return true; }
return false; }
206 #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
210 #elif JUCE_GCC || JUCE_CLANG
211 #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics
213 #if JUCE_IOS || JUCE_ANDROID // (64-bit ops will compile but not link on these mobile OSes)
214 #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
219 #define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics
221 #if JUCE_USE_MSVC_INTRINSICS
222 #ifndef __INTEL_COMPILER
223 #pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \
224 _InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier)
226 #define juce_InterlockedExchange(a, b) _InterlockedExchange(a, b)
227 #define juce_InterlockedIncrement(a) _InterlockedIncrement(a)
228 #define juce_InterlockedDecrement(a) _InterlockedDecrement(a)
229 #define juce_InterlockedExchangeAdd(a, b) _InterlockedExchangeAdd(a, b)
230 #define juce_InterlockedCompareExchange(a, b, c) _InterlockedCompareExchange(a, b, c)
231 #define juce_InterlockedCompareExchange64(a, b, c) _InterlockedCompareExchange64(a, b, c)
232 #define juce_MemoryBarrier _ReadWriteBarrier
244 #ifndef __INTEL_COMPILER
245 #pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64)
247 #define juce_InterlockedExchangeAdd64(a, b) _InterlockedExchangeAdd64(a, b)
248 #define juce_InterlockedExchange64(a, b) _InterlockedExchange64(a, b)
249 #define juce_InterlockedIncrement64(a) _InterlockedIncrement64(a)
250 #define juce_InterlockedDecrement64(a) _InterlockedDecrement64(a)
253 template <
typename Type>
static Type juce_InterlockedExchangeAdd64 (
volatile Type* a, Type b)
noexcept {
jassertfalse; Type old = *a; *a += b;
return old; }
254 template <
typename Type>
static Type juce_InterlockedExchange64 (
volatile Type* a, Type b)
noexcept {
jassertfalse; Type old = *a; *a = b;
return old; }
255 template <
typename Type>
static Type juce_InterlockedIncrement64 (
volatile Type* a)
noexcept {
jassertfalse;
return ++*a; }
256 template <
typename Type>
static Type juce_InterlockedDecrement64 (
volatile Type* a)
noexcept {
jassertfalse;
return --*a; }
257 #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
263 #pragma warning (push)
264 #pragma warning (disable: 4311) // (truncation warning)
268 template <
typename Type>
271 #if JUCE_ATOMICS_MAC_LEGACY
272 return sizeof (Type) == 4 ? castFrom32Bit ((
int32) OSAtomicAdd32Barrier ((int32_t) 0, (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value))
273 : castFrom64Bit ((
int64) OSAtomicAdd64Barrier ((int64_t) 0, (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value));
274 #elif JUCE_ATOMICS_WINDOWS
276 : castFrom64Bit ((
int64) juce_InterlockedExchangeAdd64 ((
volatile __int64*) &value, (__int64) 0));
277 #elif JUCE_ATOMICS_GCC
278 return sizeof (Type) == 4 ? castFrom32Bit ((
int32) __sync_add_and_fetch ((
volatile int32*) &value, 0))
279 : castFrom64Bit ((
int64) __sync_add_and_fetch ((
volatile int64*) &value, 0));
283 template <
typename Type>
286 #if JUCE_ATOMICS_MAC_LEGACY || JUCE_ATOMICS_GCC
287 Type currentVal = value;
288 while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
290 #elif JUCE_ATOMICS_WINDOWS
292 : castFrom64Bit ((
int64) juce_InterlockedExchange64 ((
volatile __int64*) &value, (__int64) castTo64Bit (newValue)));
296 template <
typename Type>
299 #if JUCE_ATOMICS_MAC_LEGACY
300 return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amountToAdd), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
301 : (Type) OSAtomicAdd64Barrier ((int64_t) amountToAdd, (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
302 #elif JUCE_ATOMICS_WINDOWS
303 return sizeof (Type) == 4 ? (Type) (
juce_InterlockedExchangeAdd ((
volatile long*) &value, (
long) amountToAdd) + (long) amountToAdd)
304 : (Type) (juce_InterlockedExchangeAdd64 ((
volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd);
305 #elif JUCE_ATOMICS_GCC
306 return (Type) __sync_add_and_fetch (&value, amountToAdd);
310 template <
typename Type>
313 return operator+= (negateValue (amountToSubtract));
316 template <
typename Type>
319 #if JUCE_ATOMICS_MAC_LEGACY
320 return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
321 : (Type) OSAtomicIncrement64Barrier ((JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
322 #elif JUCE_ATOMICS_WINDOWS
324 : (Type) juce_InterlockedIncrement64 ((
volatile __int64*) &value);
325 #elif JUCE_ATOMICS_GCC
326 return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) 1)
327 : (Type) __sync_add_and_fetch ((int64_t*) &value, 1);
331 template <
typename Type>
334 #if JUCE_ATOMICS_MAC_LEGACY
335 return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
336 : (Type) OSAtomicDecrement64Barrier ((JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
337 #elif JUCE_ATOMICS_WINDOWS
339 : (Type) juce_InterlockedDecrement64 ((
volatile __int64*) &value);
340 #elif JUCE_ATOMICS_GCC
341 return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) -1)
342 : (Type) __sync_add_and_fetch ((int64_t*) &value, -1);
346 template <
typename Type>
349 #if JUCE_ATOMICS_MAC_LEGACY
350 return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
351 : OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
352 #elif JUCE_ATOMICS_WINDOWS
353 return compareAndSetValue (newValue, valueToCompare) == valueToCompare;
354 #elif JUCE_ATOMICS_GCC
355 return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((
volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))
356 : __sync_bool_compare_and_swap ((
volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue));
360 template <
typename Type>
363 #if JUCE_ATOMICS_MAC_LEGACY
366 if (compareAndSetBool (newValue, valueToCompare))
367 return valueToCompare;
369 const Type result = value;
370 if (result != valueToCompare)
374 #elif JUCE_ATOMICS_WINDOWS
375 return sizeof (Type) == 4 ? castFrom32Bit ((
int32)
juce_InterlockedCompareExchange ((
volatile long*) &value, (
long) castTo32Bit (newValue), (
long) castTo32Bit (valueToCompare)))
377 #elif JUCE_ATOMICS_GCC
378 return sizeof (Type) == 4 ? castFrom32Bit ((
int32) __sync_val_compare_and_swap ((
volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)))
379 : castFrom64Bit ((
int64) __sync_val_compare_and_swap ((
volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)));
383 template <
typename Type>
386 #if JUCE_ATOMICS_MAC_LEGACY
388 #elif JUCE_ATOMICS_GCC
389 __sync_synchronize();
390 #elif JUCE_ATOMICS_WINDOWS
396 #pragma warning (pop)
399 #endif // JUCE_ATOMIC_H_INCLUDED