Browse Source

Removed a legacy Mac implementation of Atomic

tags/2021-05-28
Tom Poole 8 years ago
parent
commit
0f6cfda823
1 changed files with 163 additions and 221 deletions
  1. +163
    -221
      modules/juce_core/memory/juce_Atomic.h

+ 163
- 221
modules/juce_core/memory/juce_Atomic.h View File

@@ -144,10 +144,16 @@ namespace juce
#else #else
#ifndef DOXYGEN
template <typename Type> class AtomicBase;
#if JUCE_MSVC
JUCE_COMPILER_WARNING ("You must use a version of MSVC which supports std::atomic")
#endif #endif
#if JUCE_IOS || JUCE_ANDROID // (64-bit ops will compile but not link)
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
#endif
template <typename Type> class AtomicBase;
//============================================================================== //==============================================================================
/** /**
Simple class to hold a primitive value and perform atomic operations on it. Simple class to hold a primitive value and perform atomic operations on it.
@@ -252,227 +258,163 @@ namespace juce
static inline void memoryBarrier() noexcept { AtomicBase<Type>::memoryBarrier(); } static inline void memoryBarrier() noexcept { AtomicBase<Type>::memoryBarrier(); }
}; };
#ifndef DOXYGEN
//==============================================================================
// Internal implementation follows
//==============================================================================
template <typename Type>
class AtomicBase
{
public:
typedef typename AtomicHelpers::DiffTypeHelper<Type>::Type DiffType;
inline AtomicBase() noexcept : value (0) {}
inline explicit AtomicBase (const Type v) noexcept : value (v) {}
inline AtomicBase (const AtomicBase& other) noexcept : value (other.get()) {}
Type get() const noexcept;
inline AtomicBase& operator= (const AtomicBase<Type>& other) noexcept { exchange (other.get()); return *this; }
inline AtomicBase& operator= (const Type newValue) noexcept { exchange (newValue); return *this; }
void set (Type newValue) noexcept { exchange (newValue); }
Type exchange (Type) noexcept;
bool compareAndSetBool (Type, Type) noexcept;
Type compareAndSetValue (Type, Type) noexcept;
static void memoryBarrier() noexcept;
//==============================================================================
#if JUCE_64BIT
JUCE_ALIGN (8)
#else
JUCE_ALIGN (4)
#endif
/** The raw value that this class operates on.
This is exposed publicly in case you need to manipulate it directly
for performance reasons.
*/
volatile Type value;
protected:
template <typename Dest, typename Source>
static inline Dest castTo (Source value) noexcept { union { Dest d; Source s; } u; u.s = value; return u.d; }
static inline Type castFrom32Bit (int32 value) noexcept { return castTo <Type, int32> (value); }
static inline Type castFrom64Bit (int64 value) noexcept { return castTo <Type, int64> (value); }
static inline int32 castTo32Bit (Type value) noexcept { return castTo <int32, Type> (value); }
static inline int64 castTo64Bit (Type value) noexcept { return castTo <int64, Type> (value); }
Type operator++ (int); // better to just use pre-increment with atomics..
Type operator-- (int);
/** This templated negate function will negate pointers as well as integers */
template <typename ValueType>
inline ValueType negateValue (ValueType n) noexcept
{
return sizeof (ValueType) == 1 ? (ValueType) -(signed char) n
: (sizeof (ValueType) == 2 ? (ValueType) -(short) n
: (sizeof (ValueType) == 4 ? (ValueType) -(int) n
: ((ValueType) -(int64) n)));
}
/** This templated negate function will negate pointers as well as integers */
template <typename PointerType>
inline PointerType* negateValue (PointerType* n) noexcept
{
return reinterpret_cast<PointerType*> (-reinterpret_cast<pointer_sized_int> (n));
}
};
//==============================================================================
// Specialisation for void* which does not include the pointer arithmetic
template <>
class Atomic<void*> : public AtomicBase<void*>
{
public:
inline Atomic() noexcept {}
inline explicit Atomic (void* const initialValue) noexcept : AtomicBase<void*> (initialValue) {}
inline Atomic (const Atomic<void*>& other) noexcept : AtomicBase<void*> (other) {}
inline void* get() const noexcept { return AtomicBase<void*>::get(); }
inline Atomic& operator= (const Atomic& other) noexcept { AtomicBase<void*>::operator= (other); return *this; }
inline Atomic& operator= (void* const newValue) noexcept { AtomicBase<void*>::operator= (newValue); return *this; }
inline void set (void* newValue) noexcept { exchange (newValue); }
inline void* exchange (void* v) noexcept { return AtomicBase<void*>::exchange (v); }
inline bool compareAndSetBool (void* newValue, void* valueToCompare) noexcept { return AtomicBase<void*>::compareAndSetBool (newValue, valueToCompare); }
inline void* compareAndSetValue (void* newValue, void* valueToCompare) noexcept { return AtomicBase<void*>::compareAndSetValue (newValue, valueToCompare); }
static inline void memoryBarrier() noexcept { AtomicBase<void*>::memoryBarrier(); }
};
//==============================================================================
/*
The following code is in the header so that the atomics can be inlined where possible...
*/
#if JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
#define JUCE_ATOMICS_MAC_LEGACY 1 // Older OSX builds using gcc4.1 or earlier
#elif JUCE_GCC || JUCE_CLANG
#define JUCE_ATOMICS_GCC 1 // GCC with intrinsics
#if JUCE_IOS || JUCE_ANDROID // (64-bit ops will compile but not link on these mobile OSes)
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
#endif
#endif
template <typename Type>
struct AtomicIncrementDecrement
{
static inline Type inc (AtomicBase<Type>& a) noexcept
{
#if JUCE_ATOMICS_MAC_LEGACY
return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((volatile int32_t*) &a.value)
: (Type) OSAtomicIncrement64Barrier ((volatile int64_t*) &a.value);
#elif JUCE_ATOMICS_GCC
return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (& (a.value), (Type) 1)
: (Type) __sync_add_and_fetch ((int64_t*) & (a.value), 1);
#endif
}
static inline Type dec (AtomicBase<Type>& a) noexcept
{
#if JUCE_ATOMICS_MAC_LEGACY
return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((volatile int32_t*) &a.value)
: (Type) OSAtomicDecrement64Barrier ((volatile int64_t*) &a.value);
#elif JUCE_ATOMICS_GCC
return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (& (a.value), (Type) -1)
: (Type) __sync_add_and_fetch ((int64_t*) & (a.value), -1);
#endif
}
};
template <typename Type>
struct AtomicIncrementDecrement<Type*>
{
static inline Type* inc (Atomic<Type*>& a) noexcept { return a.operator+= (1); }
static inline Type* dec (Atomic<Type*>& a) noexcept { return a.operator-= (1); }
};
//==============================================================================
template <typename Type>
inline Type AtomicBase<Type>::get() const noexcept
{
#if JUCE_ATOMICS_MAC_LEGACY
return sizeof (Type) == 4 ? castFrom32Bit ((int32) OSAtomicAdd32Barrier ((int32_t) 0, (volatile int32_t*) &value))
: castFrom64Bit ((int64) OSAtomicAdd64Barrier ((int64_t) 0, (volatile int64_t*) &value));
#elif JUCE_ATOMICS_GCC
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0))
: castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0));
#endif
}
template <typename Type>
inline Type AtomicBase<Type>::exchange (const Type newValue) noexcept
{
#if JUCE_ATOMICS_MAC_LEGACY || JUCE_ATOMICS_GCC
Type currentVal = value;
while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
return currentVal;
#endif
}
template <typename Type>
inline Type Atomic<Type>::operator+= (const DiffType amountToAdd) noexcept
{
Type amount = (Type() + amountToAdd);
#if JUCE_ATOMICS_MAC_LEGACY
return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amount), (volatile int32_t*) &AtomicBase<Type>::value)
: (Type) OSAtomicAdd64Barrier ((int64_t) amount, (volatile int64_t*) &AtomicBase<Type>::value);
#elif JUCE_ATOMICS_GCC
return (Type) __sync_add_and_fetch (& (AtomicBase<Type>::value), amount);
#endif
}
template <typename Type>
inline Type Atomic<Type>::operator-= (const DiffType amountToSubtract) noexcept
{
return operator+= (AtomicBase<Type>::negateValue (amountToSubtract));
}
template <typename Type>
inline Type Atomic<Type>::operator++() noexcept { return AtomicIncrementDecrement<Type>::inc (*this); }
template <typename Type>
inline Type Atomic<Type>::operator--() noexcept { return AtomicIncrementDecrement<Type>::dec (*this); }
template <typename Type>
inline bool AtomicBase<Type>::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept
{
#if JUCE_ATOMICS_MAC_LEGACY
return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (volatile int32_t*) &value)
: OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (volatile int64_t*) &value);
#elif JUCE_ATOMICS_GCC
return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))
: __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue));
#endif
}
template <typename Type>
inline Type AtomicBase<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept
{
#if JUCE_ATOMICS_MAC_LEGACY
for (;;) // Annoying workaround for only having a bool CAS operation..
{
if (compareAndSetBool (newValue, valueToCompare))
return valueToCompare;
const Type result = value;
if (result != valueToCompare)
return result;
}
#elif JUCE_ATOMICS_GCC
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)))
: castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)));
//==============================================================================
// Internal implementation follows
//==============================================================================
template <typename Type>
class AtomicBase
{
public:
typedef typename AtomicHelpers::DiffTypeHelper<Type>::Type DiffType;
inline AtomicBase() noexcept : value (0) {}
inline explicit AtomicBase (const Type v) noexcept : value (v) {}
inline AtomicBase (const AtomicBase& other) noexcept : value (other.get()) {}
Type get() const noexcept;
inline AtomicBase& operator= (const AtomicBase<Type>& other) noexcept { exchange (other.get()); return *this; }
inline AtomicBase& operator= (const Type newValue) noexcept { exchange (newValue); return *this; }
void set (Type newValue) noexcept { exchange (newValue); }
Type exchange (Type) noexcept;
bool compareAndSetBool (Type, Type) noexcept;
Type compareAndSetValue (Type, Type) noexcept;
static void memoryBarrier() noexcept;
//==============================================================================
#if JUCE_64BIT
JUCE_ALIGN (8)
#else
JUCE_ALIGN (4)
#endif #endif
}
template <typename Type>
inline void AtomicBase<Type>::memoryBarrier() noexcept
{
#if JUCE_ATOMICS_MAC_LEGACY
OSMemoryBarrier();
#elif JUCE_ATOMICS_GCC
__sync_synchronize();
#endif
}
#endif
/** The raw value that this class operates on.
This is exposed publicly in case you need to manipulate it directly
for performance reasons.
*/
volatile Type value;
protected:
template <typename Dest, typename Source>
static inline Dest castTo (Source value) noexcept { union { Dest d; Source s; } u; u.s = value; return u.d; }
static inline Type castFrom32Bit (int32 value) noexcept { return castTo <Type, int32> (value); }
static inline Type castFrom64Bit (int64 value) noexcept { return castTo <Type, int64> (value); }
static inline int32 castTo32Bit (Type value) noexcept { return castTo <int32, Type> (value); }
static inline int64 castTo64Bit (Type value) noexcept { return castTo <int64, Type> (value); }
Type operator++ (int); // better to just use pre-increment with atomics..
Type operator-- (int);
/** This templated negate function will negate pointers as well as integers */
template <typename ValueType>
inline ValueType negateValue (ValueType n) noexcept
{
return sizeof (ValueType) == 1 ? (ValueType) -(signed char) n
: (sizeof (ValueType) == 2 ? (ValueType) -(short) n
: (sizeof (ValueType) == 4 ? (ValueType) -(int) n
: ((ValueType) -(int64) n)));
}
/** This templated negate function will negate pointers as well as integers */
template <typename PointerType>
inline PointerType* negateValue (PointerType* n) noexcept
{
return reinterpret_cast<PointerType*> (-reinterpret_cast<pointer_sized_int> (n));
}
};
//==============================================================================
// Specialisation for void* which does not include the pointer arithmetic
template <>
class Atomic<void*> : public AtomicBase<void*>
{
public:
inline Atomic() noexcept {}
inline explicit Atomic (void* const initialValue) noexcept : AtomicBase<void*> (initialValue) {}
inline Atomic (const Atomic<void*>& other) noexcept : AtomicBase<void*> (other) {}
inline void* get() const noexcept { return AtomicBase<void*>::get(); }
inline Atomic& operator= (const Atomic& other) noexcept { AtomicBase<void*>::operator= (other); return *this; }
inline Atomic& operator= (void* const newValue) noexcept { AtomicBase<void*>::operator= (newValue); return *this; }
inline void set (void* newValue) noexcept { exchange (newValue); }
inline void* exchange (void* v) noexcept { return AtomicBase<void*>::exchange (v); }
inline bool compareAndSetBool (void* newValue, void* valueToCompare) noexcept { return AtomicBase<void*>::compareAndSetBool (newValue, valueToCompare); }
inline void* compareAndSetValue (void* newValue, void* valueToCompare) noexcept { return AtomicBase<void*>::compareAndSetValue (newValue, valueToCompare); }
static inline void memoryBarrier() noexcept { AtomicBase<void*>::memoryBarrier(); }
};
template <typename Type>
struct AtomicIncrementDecrement
{
static inline Type inc (AtomicBase<Type>& a) noexcept
{
return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (& (a.value), (Type) 1)
: (Type) __sync_add_and_fetch ((int64_t*) & (a.value), 1);
}
static inline Type dec (AtomicBase<Type>& a) noexcept
{
return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (& (a.value), (Type) -1)
: (Type) __sync_add_and_fetch ((int64_t*) & (a.value), -1);
}
};
template <typename Type>
struct AtomicIncrementDecrement<Type*>
{
static inline Type* inc (Atomic<Type*>& a) noexcept { return a.operator+= (1); }
static inline Type* dec (Atomic<Type*>& a) noexcept { return a.operator-= (1); }
};
//==============================================================================
template <typename Type>
inline Type AtomicBase<Type>::get() const noexcept
{
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0))
: castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0));
}
template <typename Type>
inline Type AtomicBase<Type>::exchange (const Type newValue) noexcept
{
Type currentVal = value;
while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
return currentVal;
}
template <typename Type>
inline Type Atomic<Type>::operator+= (const DiffType amountToAdd) noexcept
{
Type amount = (Type() + amountToAdd);
return (Type) __sync_add_and_fetch (& (AtomicBase<Type>::value), amount);
}
template <typename Type>
inline Type Atomic<Type>::operator-= (const DiffType amountToSubtract) noexcept
{
return operator+= (AtomicBase<Type>::negateValue (amountToSubtract));
}
template <typename Type>
inline Type Atomic<Type>::operator++() noexcept { return AtomicIncrementDecrement<Type>::inc (*this); }
template <typename Type>
inline Type Atomic<Type>::operator--() noexcept { return AtomicIncrementDecrement<Type>::dec (*this); }
template <typename Type>
inline bool AtomicBase<Type>::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept
{
return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))
: __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue));
}
template <typename Type>
inline Type AtomicBase<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept
{
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)))
: castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)));
}
template <typename Type>
inline void AtomicBase<Type>::memoryBarrier() noexcept { __sync_synchronize(); }
#endif #endif


Loading…
Cancel
Save