openshot-audio  0.1.7
juce_Atomic.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the juce_core module of the JUCE library.
5  Copyright (c) 2015 - ROLI Ltd.
6 
7  Permission to use, copy, modify, and/or distribute this software for any purpose with
8  or without fee is hereby granted, provided that the above copyright notice and this
9  permission notice appear in all copies.
10 
11  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
12  TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
13  NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
15  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18  ------------------------------------------------------------------------------
19 
20  NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
21  All other JUCE modules are covered by a dual GPL/commercial license, so if you are
22  using any other modules, be sure to check that you also comply with their license.
23 
24  For more details, visit www.juce.com
25 
26  ==============================================================================
27 */
28 
29 #ifndef JUCE_ATOMIC_H_INCLUDED
30 #define JUCE_ATOMIC_H_INCLUDED
31 
32 
33 //==============================================================================
40 template <typename Type>
41 class Atomic
42 {
43 public:
45  inline Atomic() noexcept
46  : value (0)
47  {
48  }
49 
51  inline explicit Atomic (const Type initialValue) noexcept
52  : value (initialValue)
53  {
54  }
55 
57  inline Atomic (const Atomic& other) noexcept
58  : value (other.get())
59  {
60  }
61 
63  inline ~Atomic() noexcept
64  {
65  // This class can only be used for types which are 32 or 64 bits in size.
66  static_jassert (sizeof (Type) == 4 || sizeof (Type) == 8);
67  }
68 
70  Type get() const noexcept;
71 
73  inline Atomic& operator= (const Atomic& other) noexcept { exchange (other.get()); return *this; }
74 
76  inline Atomic& operator= (const Type newValue) noexcept { exchange (newValue); return *this; }
77 
79  void set (Type newValue) noexcept { exchange (newValue); }
80 
82  Type exchange (Type value) noexcept;
83 
85  Type operator+= (Type amountToAdd) noexcept;
86 
88  Type operator-= (Type amountToSubtract) noexcept;
89 
91  Type operator++() noexcept;
92 
94  Type operator--() noexcept;
95 
117  bool compareAndSetBool (Type newValue, Type valueToCompare) noexcept;
118 
137  Type compareAndSetValue (Type newValue, Type valueToCompare) noexcept;
138 
140  static void memoryBarrier() noexcept;
141 
142  //==============================================================================
143  #if JUCE_64BIT
144  JUCE_ALIGN (8)
145  #else
146  JUCE_ALIGN (4)
147  #endif
148 
153  volatile Type value;
154 
155 private:
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; }
158 
159  static inline Type castFrom32Bit (int32 value) noexcept { return castTo <Type, int32> (value); }
160  static inline Type castFrom64Bit (int64 value) noexcept { return castTo <Type, int64> (value); }
161  static inline int32 castTo32Bit (Type value) noexcept { return castTo <int32, Type> (value); }
162  static inline int64 castTo64Bit (Type value) noexcept { return castTo <int64, Type> (value); }
163 
164  Type operator++ (int); // better to just use pre-increment with atomics..
165  Type operator-- (int);
166 
168  template <typename ValueType>
169  inline ValueType negateValue (ValueType n) noexcept
170  {
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)));
175  }
176 
178  template <typename PointerType>
179  inline PointerType* negateValue (PointerType* n) noexcept
180  {
181  return reinterpret_cast <PointerType*> (-reinterpret_cast <pointer_sized_int> (n));
182  }
183 };
184 
185 
186 //==============================================================================
187 /*
188  The following code is in the header so that the atomics can be inlined where possible...
189 */
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
192 
193  #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
194  #define JUCE_MAC_ATOMICS_VOLATILE
195  #else
196  #define JUCE_MAC_ATOMICS_VOLATILE volatile
197  #endif
198 
199  #if JUCE_PPC
200  // None of these atomics are available for PPC or for iOS 3.1 or earlier!!
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
207  #endif
208 
209 //==============================================================================
210 #elif JUCE_GCC || JUCE_CLANG
211  #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics
212 
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
215  #endif
216 
217 //==============================================================================
218 #else
219  #define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics
220 
221  #if JUCE_USE_MSVC_INTRINSICS
222  #ifndef __INTEL_COMPILER
223  #pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \
224  _InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier)
225  #endif
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
233  #else
234  long juce_InterlockedExchange (volatile long* a, long b) noexcept;
235  long juce_InterlockedIncrement (volatile long* a) noexcept;
236  long juce_InterlockedDecrement (volatile long* a) noexcept;
237  long juce_InterlockedExchangeAdd (volatile long* a, long b) noexcept;
238  long juce_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept;
239  __int64 juce_InterlockedCompareExchange64 (volatile __int64* a, __int64 b, __int64 c) noexcept;
240  inline void juce_MemoryBarrier() noexcept { long x = 0; juce_InterlockedIncrement (&x); }
241  #endif
242 
243  #if JUCE_64BIT
244  #ifndef __INTEL_COMPILER
245  #pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64)
246  #endif
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)
251  #else
252  // None of these atomics are available in a 32-bit Windows build!!
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
258  #endif
259 #endif
260 
261 
262 #if JUCE_MSVC
263  #pragma warning (push)
264  #pragma warning (disable: 4311) // (truncation warning)
265 #endif
266 
267 //==============================================================================
268 template <typename Type>
269 inline Type Atomic<Type>::get() const noexcept
270 {
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
275  return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 0))
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));
280  #endif
281 }
282 
283 template <typename Type>
284 inline Type Atomic<Type>::exchange (const Type newValue) noexcept
285 {
286  #if JUCE_ATOMICS_MAC_LEGACY || JUCE_ATOMICS_GCC
287  Type currentVal = value;
288  while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
289  return currentVal;
290  #elif JUCE_ATOMICS_WINDOWS
291  return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchange ((volatile long*) &value, (long) castTo32Bit (newValue)))
292  : castFrom64Bit ((int64) juce_InterlockedExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue)));
293  #endif
294 }
295 
296 template <typename Type>
297 inline Type Atomic<Type>::operator+= (const Type amountToAdd) noexcept
298 {
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);
307  #endif
308 }
309 
310 template <typename Type>
311 inline Type Atomic<Type>::operator-= (const Type amountToSubtract) noexcept
312 {
313  return operator+= (negateValue (amountToSubtract));
314 }
315 
316 template <typename Type>
317 inline Type Atomic<Type>::operator++() noexcept
318 {
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
323  return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value)
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);
328  #endif
329 }
330 
331 template <typename Type>
332 inline Type Atomic<Type>::operator--() noexcept
333 {
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
338  return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value)
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);
343  #endif
344 }
345 
346 template <typename Type>
347 inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept
348 {
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));
357  #endif
358 }
359 
360 template <typename Type>
361 inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept
362 {
363  #if JUCE_ATOMICS_MAC_LEGACY
364  for (;;) // Annoying workaround for only having a bool CAS operation..
365  {
366  if (compareAndSetBool (newValue, valueToCompare))
367  return valueToCompare;
368 
369  const Type result = value;
370  if (result != valueToCompare)
371  return result;
372  }
373 
374  #elif JUCE_ATOMICS_WINDOWS
375  return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare)))
376  : castFrom64Bit ((int64) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (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)));
380  #endif
381 }
382 
383 template <typename Type>
384 inline void Atomic<Type>::memoryBarrier() noexcept
385 {
386  #if JUCE_ATOMICS_MAC_LEGACY
387  OSMemoryBarrier();
388  #elif JUCE_ATOMICS_GCC
389  __sync_synchronize();
390  #elif JUCE_ATOMICS_WINDOWS
392  #endif
393 }
394 
395 #if JUCE_MSVC
396  #pragma warning (pop)
397 #endif
398 
399 #endif // JUCE_ATOMIC_H_INCLUDED
static void memoryBarrier() noexcept
Definition: juce_Atomic.h:384
Atomic(const Atomic &other) noexcept
Definition: juce_Atomic.h:57
int pointer_sized_int
Definition: juce_MathsFunctions.h:86
__int64 juce_InterlockedCompareExchange64(volatile __int64 *a, __int64 b, __int64 c) noexcept
Definition: juce_win32_Threads.cpp:48
#define JUCE_ALIGN(bytes)
Definition: juce_PlatformDefs.h:303
Atomic() noexcept
Definition: juce_Atomic.h:45
#define static_jassert(expression)
Definition: juce_PlatformDefs.h:165
Type get() const noexcept
Definition: juce_Atomic.h:269
#define noexcept
Definition: juce_CompilerSupport.h:141
Definition: juce_Atomic.h:41
#define jassertfalse
Definition: juce_PlatformDefs.h:141
Type exchange(Type value) noexcept
Definition: juce_Atomic.h:284
Type operator--() noexcept
Definition: juce_Atomic.h:332
void juce_MemoryBarrier() noexcept
Definition: juce_Atomic.h:240
Type operator-=(Type amountToSubtract) noexcept
Definition: juce_Atomic.h:311
long juce_InterlockedExchangeAdd(volatile long *a, long b) noexcept
Definition: juce_win32_Threads.cpp:45
long juce_InterlockedIncrement(volatile long *a) noexcept
Definition: juce_win32_Threads.cpp:43
volatile Type value
Definition: juce_Atomic.h:153
long long int64
Definition: juce_MathsFunctions.h:60
long juce_InterlockedDecrement(volatile long *a) noexcept
Definition: juce_win32_Threads.cpp:44
Type operator++() noexcept
Definition: juce_Atomic.h:317
bool compareAndSetBool(Type newValue, Type valueToCompare) noexcept
Definition: juce_Atomic.h:347
Type operator+=(Type amountToAdd) noexcept
Definition: juce_Atomic.h:297
~Atomic() noexcept
Definition: juce_Atomic.h:63
long juce_InterlockedExchange(volatile long *a, long b) noexcept
Definition: juce_win32_Threads.cpp:42
long juce_InterlockedCompareExchange(volatile long *a, long b, long c) noexcept
Definition: juce_win32_Threads.cpp:46
Atomic & operator=(const Atomic &other) noexcept
Definition: juce_Atomic.h:73
Atomic(const Type initialValue) noexcept
Definition: juce_Atomic.h:51
Type compareAndSetValue(Type newValue, Type valueToCompare) noexcept
Definition: juce_Atomic.h:361
signed int int32
Definition: juce_MathsFunctions.h:49