- port to minGw
git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@235 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_ATOMIC_H_INCLUDED
|
||||
#define JUCE_ATOMIC_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Simple class to hold a primitive value and perform atomic operations on it.
|
||||
|
||||
The type used must be a 32 or 64 bit primitive, like an int, pointer, etc.
|
||||
There are methods to perform most of the basic atomic operations.
|
||||
*/
|
||||
template <typename Type>
|
||||
class Atomic
|
||||
{
|
||||
public:
|
||||
/** Creates a new value, initialised to zero. */
|
||||
inline Atomic() noexcept
|
||||
: value (0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a new value, with a given initial value. */
|
||||
inline explicit Atomic (const Type initialValue) noexcept
|
||||
: value (initialValue)
|
||||
{
|
||||
}
|
||||
|
||||
/** Copies another value (atomically). */
|
||||
inline Atomic (const Atomic& other) noexcept
|
||||
: value (other.get())
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
inline ~Atomic() noexcept
|
||||
{
|
||||
// This class can only be used for types which are 32 or 64 bits in size.
|
||||
static_jassert (sizeof (Type) == 4 || sizeof (Type) == 8);
|
||||
}
|
||||
|
||||
/** Atomically reads and returns the current value. */
|
||||
Type get() const noexcept;
|
||||
|
||||
/** Copies another value onto this one (atomically). */
|
||||
inline Atomic& operator= (const Atomic& other) noexcept { exchange (other.get()); return *this; }
|
||||
|
||||
/** Copies another value onto this one (atomically). */
|
||||
inline Atomic& operator= (const Type newValue) noexcept { exchange (newValue); return *this; }
|
||||
|
||||
/** Atomically sets the current value. */
|
||||
void set (Type newValue) noexcept { exchange (newValue); }
|
||||
|
||||
/** Atomically sets the current value, returning the value that was replaced. */
|
||||
Type exchange (Type value) noexcept;
|
||||
|
||||
/** Atomically adds a number to this value, returning the new value. */
|
||||
Type operator+= (Type amountToAdd) noexcept;
|
||||
|
||||
/** Atomically subtracts a number from this value, returning the new value. */
|
||||
Type operator-= (Type amountToSubtract) noexcept;
|
||||
|
||||
/** Atomically increments this value, returning the new value. */
|
||||
Type operator++() noexcept;
|
||||
|
||||
/** Atomically decrements this value, returning the new value. */
|
||||
Type operator--() noexcept;
|
||||
|
||||
/** Atomically compares this value with a target value, and if it is equal, sets
|
||||
this to be equal to a new value.
|
||||
|
||||
This operation is the atomic equivalent of doing this:
|
||||
@code
|
||||
bool compareAndSetBool (Type newValue, Type valueToCompare)
|
||||
{
|
||||
if (get() == valueToCompare)
|
||||
{
|
||||
set (newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@returns true if the comparison was true and the value was replaced; false if
|
||||
the comparison failed and the value was left unchanged.
|
||||
@see compareAndSetValue
|
||||
*/
|
||||
bool compareAndSetBool (Type newValue, Type valueToCompare) noexcept;
|
||||
|
||||
/** Atomically compares this value with a target value, and if it is equal, sets
|
||||
this to be equal to a new value.
|
||||
|
||||
This operation is the atomic equivalent of doing this:
|
||||
@code
|
||||
Type compareAndSetValue (Type newValue, Type valueToCompare)
|
||||
{
|
||||
Type oldValue = get();
|
||||
if (oldValue == valueToCompare)
|
||||
set (newValue);
|
||||
|
||||
return oldValue;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@returns the old value before it was changed.
|
||||
@see compareAndSetBool
|
||||
*/
|
||||
Type compareAndSetValue (Type newValue, Type valueToCompare) noexcept;
|
||||
|
||||
/** Implements a memory read/write barrier. */
|
||||
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 publically in case you need to manipulate it directly
|
||||
for performance reasons.
|
||||
*/
|
||||
volatile Type value;
|
||||
|
||||
private:
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/*
|
||||
The following code is in the header so that the atomics can be inlined where possible...
|
||||
*/
|
||||
#if JUCE_MAC && (JUCE_PPC || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
|
||||
#define JUCE_ATOMICS_MAC_LEGACY 1 // Older OSX builds using gcc4.1 or earlier
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
#define JUCE_MAC_ATOMICS_VOLATILE
|
||||
#else
|
||||
#define JUCE_MAC_ATOMICS_VOLATILE volatile
|
||||
#endif
|
||||
|
||||
#if JUCE_PPC
|
||||
// None of these atomics are available for PPC or for iOS 3.1 or earlier!!
|
||||
template <typename Type> static Type OSAtomicAdd64Barrier (Type b, JUCE_MAC_ATOMICS_VOLATILE Type* a) noexcept { jassertfalse; return *a += b; }
|
||||
template <typename Type> static Type OSAtomicIncrement64Barrier (JUCE_MAC_ATOMICS_VOLATILE Type* a) noexcept { jassertfalse; return ++*a; }
|
||||
template <typename Type> static Type OSAtomicDecrement64Barrier (JUCE_MAC_ATOMICS_VOLATILE Type* a) noexcept { jassertfalse; return --*a; }
|
||||
template <typename Type> static bool OSAtomicCompareAndSwap64Barrier (Type old, Type newValue, JUCE_MAC_ATOMICS_VOLATILE Type* value) noexcept
|
||||
{ jassertfalse; if (old == *value) { *value = newValue; return true; } return false; }
|
||||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#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
|
||||
|
||||
//==============================================================================
|
||||
#else
|
||||
#define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics
|
||||
|
||||
#if JUCE_USE_MSVC_INTRINSICS
|
||||
#ifndef __INTEL_COMPILER
|
||||
#pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \
|
||||
_InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier)
|
||||
#endif
|
||||
#define juce_InterlockedExchange(a, b) _InterlockedExchange(a, b)
|
||||
#define juce_InterlockedIncrement(a) _InterlockedIncrement(a)
|
||||
#define juce_InterlockedDecrement(a) _InterlockedDecrement(a)
|
||||
#define juce_InterlockedExchangeAdd(a, b) _InterlockedExchangeAdd(a, b)
|
||||
#define juce_InterlockedCompareExchange(a, b, c) _InterlockedCompareExchange(a, b, c)
|
||||
#define juce_InterlockedCompareExchange64(a, b, c) _InterlockedCompareExchange64(a, b, c)
|
||||
#define juce_MemoryBarrier _ReadWriteBarrier
|
||||
#else
|
||||
long juce_InterlockedExchange (volatile long* a, long b) noexcept;
|
||||
long juce_InterlockedIncrement (volatile long* a) noexcept;
|
||||
long juce_InterlockedDecrement (volatile long* a) noexcept;
|
||||
long juce_InterlockedExchangeAdd (volatile long* a, long b) noexcept;
|
||||
long juce_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept;
|
||||
__int64 juce_InterlockedCompareExchange64 (volatile __int64* a, __int64 b, __int64 c) noexcept;
|
||||
inline void juce_MemoryBarrier() noexcept { long x = 0; juce_InterlockedIncrement (&x); }
|
||||
#endif
|
||||
|
||||
#if JUCE_64BIT
|
||||
#ifndef __INTEL_COMPILER
|
||||
#pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64)
|
||||
#endif
|
||||
#define juce_InterlockedExchangeAdd64(a, b) _InterlockedExchangeAdd64(a, b)
|
||||
#define juce_InterlockedExchange64(a, b) _InterlockedExchange64(a, b)
|
||||
#define juce_InterlockedIncrement64(a) _InterlockedIncrement64(a)
|
||||
#define juce_InterlockedDecrement64(a) _InterlockedDecrement64(a)
|
||||
#else
|
||||
// None of these atomics are available in a 32-bit Windows build!!
|
||||
template <typename Type> static Type juce_InterlockedExchangeAdd64 (volatile Type* a, Type b) noexcept { jassertfalse; Type old = *a; *a += b; return old; }
|
||||
template <typename Type> static Type juce_InterlockedExchange64 (volatile Type* a, Type b) noexcept { jassertfalse; Type old = *a; *a = b; return old; }
|
||||
template <typename Type> static Type juce_InterlockedIncrement64 (volatile Type* a) noexcept { jassertfalse; return ++*a; }
|
||||
template <typename Type> static Type juce_InterlockedDecrement64 (volatile Type* a) noexcept { jassertfalse; return --*a; }
|
||||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4311) // (truncation warning)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::get() const noexcept
|
||||
{
|
||||
#if JUCE_ATOMICS_MAC_LEGACY
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) OSAtomicAdd32Barrier ((int32_t) 0, (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value))
|
||||
: castFrom64Bit ((int64) OSAtomicAdd64Barrier ((int64_t) 0, (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value));
|
||||
#elif JUCE_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 0))
|
||||
: castFrom64Bit ((int64) juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0));
|
||||
#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 Atomic<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;
|
||||
#elif JUCE_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchange ((volatile long*) &value, (long) castTo32Bit (newValue)))
|
||||
: castFrom64Bit ((int64) juce_InterlockedExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue)));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator+= (const Type amountToAdd) noexcept
|
||||
{
|
||||
#if JUCE_ATOMICS_MAC_LEGACY
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amountToAdd), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicAdd64Barrier ((int64_t) amountToAdd, (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif JUCE_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd)
|
||||
: (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd);
|
||||
#elif JUCE_ATOMICS_GCC
|
||||
return (Type) __sync_add_and_fetch (&value, amountToAdd);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator-= (const Type amountToSubtract) noexcept
|
||||
{
|
||||
return operator+= (negateValue (amountToSubtract));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator++() noexcept
|
||||
{
|
||||
#if JUCE_ATOMICS_MAC_LEGACY
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicIncrement64Barrier ((JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif JUCE_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value)
|
||||
: (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value);
|
||||
#elif JUCE_ATOMICS_GCC
|
||||
return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) 1)
|
||||
: (Type) __sync_add_and_fetch ((int64_t*) &value, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator--() noexcept
|
||||
{
|
||||
#if JUCE_ATOMICS_MAC_LEGACY
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicDecrement64Barrier ((JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif JUCE_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value)
|
||||
: (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value);
|
||||
#elif JUCE_ATOMICS_GCC
|
||||
return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) -1)
|
||||
: (Type) __sync_add_and_fetch ((int64_t*) &value, -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool Atomic<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), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif JUCE_ATOMICS_WINDOWS
|
||||
return compareAndSetValue (newValue, valueToCompare) == valueToCompare;
|
||||
#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 Atomic<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_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare)))
|
||||
: castFrom64Bit ((int64) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare)));
|
||||
#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)));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void Atomic<Type>::memoryBarrier() noexcept
|
||||
{
|
||||
#if JUCE_ATOMICS_MAC_LEGACY
|
||||
OSMemoryBarrier();
|
||||
#elif JUCE_ATOMICS_GCC
|
||||
__sync_synchronize();
|
||||
#elif JUCE_ATOMICS_WINDOWS
|
||||
juce_MemoryBarrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif // JUCE_ATOMIC_H_INCLUDED
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_BYTEORDER_H_INCLUDED
|
||||
#define JUCE_BYTEORDER_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Contains static methods for converting the byte order between different
|
||||
endiannesses.
|
||||
*/
|
||||
class JUCE_API ByteOrder
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Swaps the upper and lower bytes of a 16-bit integer. */
|
||||
static uint16 swap (uint16 value) noexcept;
|
||||
|
||||
/** Reverses the order of the 4 bytes in a 32-bit integer. */
|
||||
static uint32 swap (uint32 value) noexcept;
|
||||
|
||||
/** Reverses the order of the 8 bytes in a 64-bit integer. */
|
||||
static uint64 swap (uint64 value) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Swaps the byte order of a 16-bit int if the CPU is big-endian */
|
||||
static uint16 swapIfBigEndian (uint16 value) noexcept;
|
||||
|
||||
/** Swaps the byte order of a 32-bit int if the CPU is big-endian */
|
||||
static uint32 swapIfBigEndian (uint32 value) noexcept;
|
||||
|
||||
/** Swaps the byte order of a 64-bit int if the CPU is big-endian */
|
||||
static uint64 swapIfBigEndian (uint64 value) noexcept;
|
||||
|
||||
/** Swaps the byte order of a 16-bit int if the CPU is little-endian */
|
||||
static uint16 swapIfLittleEndian (uint16 value) noexcept;
|
||||
|
||||
/** Swaps the byte order of a 32-bit int if the CPU is little-endian */
|
||||
static uint32 swapIfLittleEndian (uint32 value) noexcept;
|
||||
|
||||
/** Swaps the byte order of a 64-bit int if the CPU is little-endian */
|
||||
static uint64 swapIfLittleEndian (uint64 value) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Turns 4 bytes into a little-endian integer. */
|
||||
static uint32 littleEndianInt (const void* bytes) noexcept;
|
||||
|
||||
/** Turns 8 bytes into a little-endian integer. */
|
||||
static uint64 littleEndianInt64 (const void* bytes) noexcept;
|
||||
|
||||
/** Turns 2 bytes into a little-endian integer. */
|
||||
static uint16 littleEndianShort (const void* bytes) noexcept;
|
||||
|
||||
/** Turns 4 bytes into a big-endian integer. */
|
||||
static uint32 bigEndianInt (const void* bytes) noexcept;
|
||||
|
||||
/** Turns 8 bytes into a big-endian integer. */
|
||||
static uint64 bigEndianInt64 (const void* bytes) noexcept;
|
||||
|
||||
/** Turns 2 bytes into a big-endian integer. */
|
||||
static uint16 bigEndianShort (const void* bytes) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
|
||||
static int littleEndian24Bit (const void* bytes) noexcept;
|
||||
|
||||
/** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
|
||||
static int bigEndian24Bit (const void* bytes) noexcept;
|
||||
|
||||
/** Copies a 24-bit number to 3 little-endian bytes. */
|
||||
static void littleEndian24BitToChars (int value, void* destBytes) noexcept;
|
||||
|
||||
/** Copies a 24-bit number to 3 big-endian bytes. */
|
||||
static void bigEndian24BitToChars (int value, void* destBytes) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the current CPU is big-endian. */
|
||||
static bool isBigEndian() noexcept;
|
||||
|
||||
private:
|
||||
ByteOrder() JUCE_DELETED_FUNCTION;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (ByteOrder)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_USE_MSVC_INTRINSICS && ! defined (__INTEL_COMPILER)
|
||||
#pragma intrinsic (_byteswap_ulong)
|
||||
#endif
|
||||
|
||||
inline uint16 ByteOrder::swap (uint16 n) noexcept
|
||||
{
|
||||
#if JUCE_USE_MSVC_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic!
|
||||
return static_cast<uint16> (_byteswap_ushort (n));
|
||||
#else
|
||||
return static_cast<uint16> ((n << 8) | (n >> 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32 ByteOrder::swap (uint32 n) noexcept
|
||||
{
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
return OSSwapInt32 (n);
|
||||
#elif JUCE_GCC && JUCE_INTEL && ! JUCE_NO_INLINE_ASM
|
||||
asm("bswap %%eax" : "=a"(n) : "a"(n));
|
||||
return n;
|
||||
#elif JUCE_USE_MSVC_INTRINSICS
|
||||
return _byteswap_ulong (n);
|
||||
#elif JUCE_MSVC && ! JUCE_NO_INLINE_ASM
|
||||
__asm {
|
||||
mov eax, n
|
||||
bswap eax
|
||||
mov n, eax
|
||||
}
|
||||
return n;
|
||||
#elif JUCE_ANDROID
|
||||
return bswap_32 (n);
|
||||
#else
|
||||
return (n << 24) | (n >> 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64 ByteOrder::swap (uint64 value) noexcept
|
||||
{
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
return OSSwapInt64 (value);
|
||||
#elif JUCE_USE_MSVC_INTRINSICS
|
||||
return _byteswap_uint64 (value);
|
||||
#else
|
||||
return (((int64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if JUCE_LITTLE_ENDIAN
|
||||
inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return v; }
|
||||
inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept { return v; }
|
||||
inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept { return v; }
|
||||
inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return swap (v); }
|
||||
inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return swap (v); }
|
||||
inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return swap (v); }
|
||||
inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return *static_cast<const uint32*> (bytes); }
|
||||
inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return *static_cast<const uint64*> (bytes); }
|
||||
inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return *static_cast<const uint16*> (bytes); }
|
||||
inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return swap (*static_cast<const uint32*> (bytes)); }
|
||||
inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast<const uint64*> (bytes)); }
|
||||
inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return swap (*static_cast<const uint16*> (bytes)); }
|
||||
inline bool ByteOrder::isBigEndian() noexcept { return false; }
|
||||
#else
|
||||
inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return swap (v); }
|
||||
inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept { return swap (v); }
|
||||
inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept { return swap (v); }
|
||||
inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return v; }
|
||||
inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return v; }
|
||||
inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return v; }
|
||||
inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return swap (*static_cast<const uint32*> (bytes)); }
|
||||
inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast<const uint64*> (bytes)); }
|
||||
inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return swap (*static_cast<const uint16*> (bytes)); }
|
||||
inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return *static_cast<const uint32*> (bytes); }
|
||||
inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return *static_cast<const uint64*> (bytes); }
|
||||
inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return *static_cast<const uint16*> (bytes); }
|
||||
inline bool ByteOrder::isBigEndian() noexcept { return true; }
|
||||
#endif
|
||||
|
||||
inline int ByteOrder::littleEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast<const int8*> (bytes)[2]) << 16) | (((int) static_cast<const uint8*> (bytes)[1]) << 8) | ((int) static_cast<const uint8*> (bytes)[0]); }
|
||||
inline int ByteOrder::bigEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast<const int8*> (bytes)[0]) << 16) | (((int) static_cast<const uint8*> (bytes)[1]) << 8) | ((int) static_cast<const uint8*> (bytes)[2]); }
|
||||
inline void ByteOrder::littleEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast<uint8*> (destBytes)[0] = (uint8) value; static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) (value >> 16); }
|
||||
inline void ByteOrder::bigEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast<uint8*> (destBytes)[0] = (uint8) (value >> 16); static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) value; }
|
||||
|
||||
|
||||
#endif // JUCE_BYTEORDER_H_INCLUDED
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_CONTAINERDELETEPOLICY_H_INCLUDED
|
||||
#define JUCE_CONTAINERDELETEPOLICY_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Used by container classes as an indirect way to delete an object of a
|
||||
particular type.
|
||||
|
||||
The generic implementation of this class simply calls 'delete', but you can
|
||||
create a specialised version of it for a particular class if you need to
|
||||
delete that type of object in a more appropriate way.
|
||||
|
||||
@see ScopedPointer, OwnedArray
|
||||
*/
|
||||
template <typename ObjectType>
|
||||
struct ContainerDeletePolicy
|
||||
{
|
||||
static void destroy (ObjectType* object)
|
||||
{
|
||||
delete object;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_CONTAINERDELETEPOLICY_H_INCLUDED
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_HEAPBLOCK_H_INCLUDED
|
||||
#define JUCE_HEAPBLOCK_H_INCLUDED
|
||||
|
||||
#ifndef DOXYGEN
|
||||
namespace HeapBlockHelper
|
||||
{
|
||||
template <bool shouldThrow>
|
||||
struct ThrowOnFail { static void check (void*) {} };
|
||||
|
||||
template<>
|
||||
struct ThrowOnFail <true> { static void check (void* data) { if (data == nullptr) throw std::bad_alloc(); } };
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Very simple container class to hold a pointer to some data on the heap.
|
||||
|
||||
When you need to allocate some heap storage for something, always try to use
|
||||
this class instead of allocating the memory directly using malloc/free.
|
||||
|
||||
A HeapBlock<char> object can be treated in pretty much exactly the same way
|
||||
as an char*, but as long as you allocate it on the stack or as a class member,
|
||||
it's almost impossible for it to leak memory.
|
||||
|
||||
It also makes your code much more concise and readable than doing the same thing
|
||||
using direct allocations,
|
||||
|
||||
E.g. instead of this:
|
||||
@code
|
||||
int* temp = (int*) malloc (1024 * sizeof (int));
|
||||
memcpy (temp, xyz, 1024 * sizeof (int));
|
||||
free (temp);
|
||||
temp = (int*) calloc (2048 * sizeof (int));
|
||||
temp[0] = 1234;
|
||||
memcpy (foobar, temp, 2048 * sizeof (int));
|
||||
free (temp);
|
||||
@endcode
|
||||
|
||||
..you could just write this:
|
||||
@code
|
||||
HeapBlock <int> temp (1024);
|
||||
memcpy (temp, xyz, 1024 * sizeof (int));
|
||||
temp.calloc (2048);
|
||||
temp[0] = 1234;
|
||||
memcpy (foobar, temp, 2048 * sizeof (int));
|
||||
@endcode
|
||||
|
||||
The class is extremely lightweight, containing only a pointer to the
|
||||
data, and exposes malloc/realloc/calloc/free methods that do the same jobs
|
||||
as their less object-oriented counterparts. Despite adding safety, you probably
|
||||
won't sacrifice any performance by using this in place of normal pointers.
|
||||
|
||||
The throwOnFailure template parameter can be set to true if you'd like the class
|
||||
to throw a std::bad_alloc exception when an allocation fails. If this is false,
|
||||
then a failed allocation will just leave the heapblock with a null pointer (assuming
|
||||
that the system's malloc() function doesn't throw).
|
||||
|
||||
@see Array, OwnedArray, MemoryBlock
|
||||
*/
|
||||
template <class ElementType, bool throwOnFailure = false>
|
||||
class HeapBlock
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a HeapBlock which is initially just a null pointer.
|
||||
|
||||
After creation, you can resize the array using the malloc(), calloc(),
|
||||
or realloc() methods.
|
||||
*/
|
||||
HeapBlock() noexcept : data (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a HeapBlock containing a number of elements.
|
||||
|
||||
The contents of the block are undefined, as it will have been created by a
|
||||
malloc call.
|
||||
|
||||
If you want an array of zero values, you can use the calloc() method or the
|
||||
other constructor that takes an InitialisationState parameter.
|
||||
*/
|
||||
explicit HeapBlock (const size_t numElements)
|
||||
: data (static_cast <ElementType*> (std::malloc (numElements * sizeof (ElementType))))
|
||||
{
|
||||
throwOnAllocationFailure();
|
||||
}
|
||||
|
||||
/** Creates a HeapBlock containing a number of elements.
|
||||
|
||||
The initialiseToZero parameter determines whether the new memory should be cleared,
|
||||
or left uninitialised.
|
||||
*/
|
||||
HeapBlock (const size_t numElements, const bool initialiseToZero)
|
||||
: data (static_cast <ElementType*> (initialiseToZero
|
||||
? std::calloc (numElements, sizeof (ElementType))
|
||||
: std::malloc (numElements * sizeof (ElementType))))
|
||||
{
|
||||
throwOnAllocationFailure();
|
||||
}
|
||||
|
||||
/** Destructor.
|
||||
This will free the data, if any has been allocated.
|
||||
*/
|
||||
~HeapBlock()
|
||||
{
|
||||
std::free (data);
|
||||
}
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
HeapBlock (HeapBlock&& other) noexcept
|
||||
: data (other.data)
|
||||
{
|
||||
other.data = nullptr;
|
||||
}
|
||||
|
||||
HeapBlock& operator= (HeapBlock&& other) noexcept
|
||||
{
|
||||
std::swap (data, other.data);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a raw pointer to the allocated data.
|
||||
This may be a null pointer if the data hasn't yet been allocated, or if it has been
|
||||
freed by calling the free() method.
|
||||
*/
|
||||
inline operator ElementType*() const noexcept { return data; }
|
||||
|
||||
/** Returns a raw pointer to the allocated data.
|
||||
This may be a null pointer if the data hasn't yet been allocated, or if it has been
|
||||
freed by calling the free() method.
|
||||
*/
|
||||
inline ElementType* getData() const noexcept { return data; }
|
||||
|
||||
/** Returns a void pointer to the allocated data.
|
||||
This may be a null pointer if the data hasn't yet been allocated, or if it has been
|
||||
freed by calling the free() method.
|
||||
*/
|
||||
inline operator void*() const noexcept { return static_cast <void*> (data); }
|
||||
|
||||
/** Returns a void pointer to the allocated data.
|
||||
This may be a null pointer if the data hasn't yet been allocated, or if it has been
|
||||
freed by calling the free() method.
|
||||
*/
|
||||
inline operator const void*() const noexcept { return static_cast <const void*> (data); }
|
||||
|
||||
/** Lets you use indirect calls to the first element in the array.
|
||||
Obviously this will cause problems if the array hasn't been initialised, because it'll
|
||||
be referencing a null pointer.
|
||||
*/
|
||||
inline ElementType* operator->() const noexcept { return data; }
|
||||
|
||||
/** Returns a reference to one of the data elements.
|
||||
Obviously there's no bounds-checking here, as this object is just a dumb pointer and
|
||||
has no idea of the size it currently has allocated.
|
||||
*/
|
||||
template <typename IndexType>
|
||||
inline ElementType& operator[] (IndexType index) const noexcept { return data [index]; }
|
||||
|
||||
/** Returns a pointer to a data element at an offset from the start of the array.
|
||||
This is the same as doing pointer arithmetic on the raw pointer itself.
|
||||
*/
|
||||
template <typename IndexType>
|
||||
inline ElementType* operator+ (IndexType index) const noexcept { return data + index; }
|
||||
|
||||
//==============================================================================
|
||||
/** Compares the pointer with another pointer.
|
||||
This can be handy for checking whether this is a null pointer.
|
||||
*/
|
||||
inline bool operator== (const ElementType* const otherPointer) const noexcept { return otherPointer == data; }
|
||||
|
||||
/** Compares the pointer with another pointer.
|
||||
This can be handy for checking whether this is a null pointer.
|
||||
*/
|
||||
inline bool operator!= (const ElementType* const otherPointer) const noexcept { return otherPointer != data; }
|
||||
|
||||
//==============================================================================
|
||||
/** Allocates a specified amount of memory.
|
||||
|
||||
This uses the normal malloc to allocate an amount of memory for this object.
|
||||
Any previously allocated memory will be freed by this method.
|
||||
|
||||
The number of bytes allocated will be (newNumElements * elementSize). Normally
|
||||
you wouldn't need to specify the second parameter, but it can be handy if you need
|
||||
to allocate a size in bytes rather than in terms of the number of elements.
|
||||
|
||||
The data that is allocated will be freed when this object is deleted, or when you
|
||||
call free() or any of the allocation methods.
|
||||
*/
|
||||
void malloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType))
|
||||
{
|
||||
std::free (data);
|
||||
data = static_cast <ElementType*> (std::malloc (newNumElements * elementSize));
|
||||
throwOnAllocationFailure();
|
||||
}
|
||||
|
||||
/** Allocates a specified amount of memory and clears it.
|
||||
This does the same job as the malloc() method, but clears the memory that it allocates.
|
||||
*/
|
||||
void calloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType))
|
||||
{
|
||||
std::free (data);
|
||||
data = static_cast <ElementType*> (std::calloc (newNumElements, elementSize));
|
||||
throwOnAllocationFailure();
|
||||
}
|
||||
|
||||
/** Allocates a specified amount of memory and optionally clears it.
|
||||
This does the same job as either malloc() or calloc(), depending on the
|
||||
initialiseToZero parameter.
|
||||
*/
|
||||
void allocate (const size_t newNumElements, bool initialiseToZero)
|
||||
{
|
||||
std::free (data);
|
||||
data = static_cast <ElementType*> (initialiseToZero
|
||||
? std::calloc (newNumElements, sizeof (ElementType))
|
||||
: std::malloc (newNumElements * sizeof (ElementType)));
|
||||
throwOnAllocationFailure();
|
||||
}
|
||||
|
||||
/** Re-allocates a specified amount of memory.
|
||||
|
||||
The semantics of this method are the same as malloc() and calloc(), but it
|
||||
uses realloc() to keep as much of the existing data as possible.
|
||||
*/
|
||||
void realloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType))
|
||||
{
|
||||
data = static_cast <ElementType*> (data == nullptr ? std::malloc (newNumElements * elementSize)
|
||||
: std::realloc (data, newNumElements * elementSize));
|
||||
throwOnAllocationFailure();
|
||||
}
|
||||
|
||||
/** Frees any currently-allocated data.
|
||||
This will free the data and reset this object to be a null pointer.
|
||||
*/
|
||||
void free()
|
||||
{
|
||||
std::free (data);
|
||||
data = nullptr;
|
||||
}
|
||||
|
||||
/** Swaps this object's data with the data of another HeapBlock.
|
||||
The two objects simply exchange their data pointers.
|
||||
*/
|
||||
template <bool otherBlockThrows>
|
||||
void swapWith (HeapBlock <ElementType, otherBlockThrows>& other) noexcept
|
||||
{
|
||||
std::swap (data, other.data);
|
||||
}
|
||||
|
||||
/** This fills the block with zeros, up to the number of elements specified.
|
||||
Since the block has no way of knowing its own size, you must make sure that the number of
|
||||
elements you specify doesn't exceed the allocated size.
|
||||
*/
|
||||
void clear (size_t numElements) noexcept
|
||||
{
|
||||
zeromem (data, sizeof (ElementType) * numElements);
|
||||
}
|
||||
|
||||
/** This typedef can be used to get the type of the heapblock's elements. */
|
||||
typedef ElementType Type;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
ElementType* data;
|
||||
|
||||
void throwOnAllocationFailure() const
|
||||
{
|
||||
HeapBlockHelper::ThrowOnFail<throwOnFailure>::check (data);
|
||||
}
|
||||
|
||||
#if ! (defined (JUCE_DLL) || defined (JUCE_DLL_BUILD))
|
||||
JUCE_DECLARE_NON_COPYABLE (HeapBlock)
|
||||
JUCE_PREVENT_HEAP_ALLOCATION // Creating a 'new HeapBlock' would be missing the point!
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_HEAPBLOCK_H_INCLUDED
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_LEAKEDOBJECTDETECTOR_H_INCLUDED
|
||||
#define JUCE_LEAKEDOBJECTDETECTOR_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Embedding an instance of this class inside another class can be used as a low-overhead
|
||||
way of detecting leaked instances.
|
||||
|
||||
This class keeps an internal static count of the number of instances that are
|
||||
active, so that when the app is shutdown and the static destructors are called,
|
||||
it can check whether there are any left-over instances that may have been leaked.
|
||||
|
||||
To use it, use the JUCE_LEAK_DETECTOR macro as a simple way to put one in your
|
||||
class declaration. Have a look through the juce codebase for examples, it's used
|
||||
in most of the classes.
|
||||
*/
|
||||
template <class OwnerClass>
|
||||
class LeakedObjectDetector
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
LeakedObjectDetector() noexcept { ++(getCounter().numObjects); }
|
||||
LeakedObjectDetector (const LeakedObjectDetector&) noexcept { ++(getCounter().numObjects); }
|
||||
|
||||
~LeakedObjectDetector()
|
||||
{
|
||||
if (--(getCounter().numObjects) < 0)
|
||||
{
|
||||
DBG ("*** Dangling pointer deletion! Class: " << getLeakedObjectClassName());
|
||||
|
||||
/** If you hit this, then you've managed to delete more instances of this class than you've
|
||||
created.. That indicates that you're deleting some dangling pointers.
|
||||
|
||||
Note that although this assertion will have been triggered during a destructor, it might
|
||||
not be this particular deletion that's at fault - the incorrect one may have happened
|
||||
at an earlier point in the program, and simply not been detected until now.
|
||||
|
||||
Most errors like this are caused by using old-fashioned, non-RAII techniques for
|
||||
your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
|
||||
ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
|
||||
*/
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class LeakCounter
|
||||
{
|
||||
public:
|
||||
LeakCounter() noexcept {}
|
||||
|
||||
~LeakCounter()
|
||||
{
|
||||
if (numObjects.value > 0)
|
||||
{
|
||||
DBG ("*** Leaked objects detected: " << numObjects.value << " instance(s) of class " << getLeakedObjectClassName());
|
||||
|
||||
/** If you hit this, then you've leaked one or more objects of the type specified by
|
||||
the 'OwnerClass' template parameter - the name should have been printed by the line above.
|
||||
|
||||
If you're leaking, it's probably because you're using old-fashioned, non-RAII techniques for
|
||||
your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
|
||||
ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
|
||||
*/
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
|
||||
Atomic<int> numObjects;
|
||||
};
|
||||
|
||||
static const char* getLeakedObjectClassName()
|
||||
{
|
||||
return OwnerClass::getLeakedObjectClassName();
|
||||
}
|
||||
|
||||
static LeakCounter& getCounter() noexcept
|
||||
{
|
||||
static LeakCounter counter;
|
||||
return counter;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
#if DOXYGEN || ! defined (JUCE_LEAK_DETECTOR)
|
||||
#if (DOXYGEN || JUCE_CHECK_MEMORY_LEAKS)
|
||||
/** This macro lets you embed a leak-detecting object inside a class.
|
||||
|
||||
To use it, simply declare a JUCE_LEAK_DETECTOR(YourClassName) inside a private section
|
||||
of the class declaration. E.g.
|
||||
|
||||
@code
|
||||
class MyClass
|
||||
{
|
||||
public:
|
||||
MyClass();
|
||||
void blahBlah();
|
||||
|
||||
private:
|
||||
JUCE_LEAK_DETECTOR (MyClass)
|
||||
};
|
||||
@endcode
|
||||
|
||||
@see JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR, LeakedObjectDetector
|
||||
*/
|
||||
#define JUCE_LEAK_DETECTOR(OwnerClass) \
|
||||
friend class juce::LeakedObjectDetector<OwnerClass>; \
|
||||
static const char* getLeakedObjectClassName() noexcept { return #OwnerClass; } \
|
||||
juce::LeakedObjectDetector<OwnerClass> JUCE_JOIN_MACRO (leakDetector, __LINE__);
|
||||
#else
|
||||
#define JUCE_LEAK_DETECTOR(OwnerClass)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // JUCE_LEAKEDOBJECTDETECTOR_H_INCLUDED
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_MEMORY_H_INCLUDED
|
||||
#define JUCE_MEMORY_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/** Fills a block of memory with zeros. */
|
||||
inline void zeromem (void* memory, size_t numBytes) noexcept { memset (memory, 0, numBytes); }
|
||||
|
||||
/** Overwrites a structure or object with zeros. */
|
||||
template <typename Type>
|
||||
inline void zerostruct (Type& structure) noexcept { memset (&structure, 0, sizeof (structure)); }
|
||||
|
||||
/** Delete an object pointer, and sets the pointer to null.
|
||||
|
||||
Remember that it's not good c++ practice to use delete directly - always try to use a ScopedPointer
|
||||
or other automatic lifetime-management system rather than resorting to deleting raw pointers!
|
||||
*/
|
||||
template <typename Type>
|
||||
inline void deleteAndZero (Type& pointer) { delete pointer; pointer = nullptr; }
|
||||
|
||||
/** A handy function which adds a number of bytes to any type of pointer and returns the result.
|
||||
This can be useful to avoid casting pointers to a char* and back when you want to move them by
|
||||
a specific number of bytes,
|
||||
*/
|
||||
template <typename Type, typename IntegerType>
|
||||
inline Type* addBytesToPointer (Type* pointer, IntegerType bytes) noexcept { return (Type*) (((char*) pointer) + bytes); }
|
||||
|
||||
/** A handy function which returns the difference between any two pointers, in bytes.
|
||||
The address of the second pointer is subtracted from the first, and the difference in bytes is returned.
|
||||
*/
|
||||
template <typename Type1, typename Type2>
|
||||
inline int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept { return (int) (((const char*) pointer1) - (const char*) pointer2); }
|
||||
|
||||
/** If a pointer is non-null, this returns a new copy of the object that it points to, or safely returns
|
||||
nullptr if the pointer is null.
|
||||
*/
|
||||
template <class Type>
|
||||
inline Type* createCopyIfNotNull (const Type* pointer) { return pointer != nullptr ? new Type (*pointer) : nullptr; }
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MAC || JUCE_IOS || DOXYGEN
|
||||
|
||||
/** A handy C++ wrapper that creates and deletes an NSAutoreleasePool object using RAII.
|
||||
You should use the JUCE_AUTORELEASEPOOL macro to create a local auto-release pool on the stack.
|
||||
*/
|
||||
class JUCE_API ScopedAutoReleasePool
|
||||
{
|
||||
public:
|
||||
ScopedAutoReleasePool();
|
||||
~ScopedAutoReleasePool();
|
||||
|
||||
private:
|
||||
void* pool;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (ScopedAutoReleasePool)
|
||||
};
|
||||
|
||||
/** A macro that can be used to easily declare a local ScopedAutoReleasePool
|
||||
object for RAII-based obj-C autoreleasing.
|
||||
Because this may use the \@autoreleasepool syntax, you must follow the macro with
|
||||
a set of braces to mark the scope of the pool.
|
||||
*/
|
||||
#if (JUCE_COMPILER_SUPPORTS_ARC && defined (__OBJC__)) || DOXYGEN
|
||||
#define JUCE_AUTORELEASEPOOL @autoreleasepool
|
||||
#else
|
||||
#define JUCE_AUTORELEASEPOOL const juce::ScopedAutoReleasePool JUCE_JOIN_MACRO (autoReleasePool_, __LINE__);
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define JUCE_AUTORELEASEPOOL
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/* In a Windows DLL build, we'll expose some malloc/free functions that live inside the DLL, and use these for
|
||||
allocating all the objects - that way all juce objects in the DLL and in the host will live in the same heap,
|
||||
avoiding problems when an object is created in one module and passed across to another where it is deleted.
|
||||
By piggy-backing on the JUCE_LEAK_DETECTOR macro, these allocators can be injected into most juce classes.
|
||||
*/
|
||||
#if JUCE_MSVC && (defined (JUCE_DLL) || defined (JUCE_DLL_BUILD)) && ! (JUCE_DISABLE_DLL_ALLOCATORS || DOXYGEN)
|
||||
extern JUCE_API void* juceDLL_malloc (size_t);
|
||||
extern JUCE_API void juceDLL_free (void*);
|
||||
|
||||
#define JUCE_LEAK_DETECTOR(OwnerClass) public:\
|
||||
static void* operator new (size_t sz) { return juce::juceDLL_malloc (sz); } \
|
||||
static void* operator new (size_t, void* p) { return p; } \
|
||||
static void operator delete (void* p) { juce::juceDLL_free (p); } \
|
||||
static void operator delete (void*, void*) {}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/** (Deprecated) This was a Windows-specific way of checking for object leaks - now please
|
||||
use the JUCE_LEAK_DETECTOR instead.
|
||||
*/
|
||||
#ifndef juce_UseDebuggingNewOperator
|
||||
#define juce_UseDebuggingNewOperator
|
||||
#endif
|
||||
|
||||
|
||||
#endif // JUCE_MEMORY_H_INCLUDED
|
||||
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
MemoryBlock::MemoryBlock() noexcept
|
||||
: size (0)
|
||||
{
|
||||
}
|
||||
|
||||
MemoryBlock::MemoryBlock (const size_t initialSize, const bool initialiseToZero)
|
||||
{
|
||||
if (initialSize > 0)
|
||||
{
|
||||
size = initialSize;
|
||||
data.allocate (initialSize, initialiseToZero);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryBlock::MemoryBlock (const MemoryBlock& other)
|
||||
: size (other.size)
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
jassert (other.data != nullptr);
|
||||
data.malloc (size);
|
||||
memcpy (data, other.data, size);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryBlock::MemoryBlock (const void* const dataToInitialiseFrom, const size_t sizeInBytes)
|
||||
: size (sizeInBytes)
|
||||
{
|
||||
jassert (((ssize_t) sizeInBytes) >= 0);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
jassert (dataToInitialiseFrom != nullptr); // non-zero size, but a zero pointer passed-in?
|
||||
|
||||
data.malloc (size);
|
||||
|
||||
if (dataToInitialiseFrom != nullptr)
|
||||
memcpy (data, dataToInitialiseFrom, size);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryBlock::~MemoryBlock() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
MemoryBlock& MemoryBlock::operator= (const MemoryBlock& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
setSize (other.size, false);
|
||||
memcpy (data, other.data, size);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
MemoryBlock::MemoryBlock (MemoryBlock&& other) noexcept
|
||||
: data (static_cast<HeapBlock<char>&&> (other.data)),
|
||||
size (other.size)
|
||||
{
|
||||
}
|
||||
|
||||
MemoryBlock& MemoryBlock::operator= (MemoryBlock&& other) noexcept
|
||||
{
|
||||
data = static_cast<HeapBlock<char>&&> (other.data);
|
||||
size = other.size;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//==============================================================================
|
||||
bool MemoryBlock::operator== (const MemoryBlock& other) const noexcept
|
||||
{
|
||||
return matches (other.data, other.size);
|
||||
}
|
||||
|
||||
bool MemoryBlock::operator!= (const MemoryBlock& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
bool MemoryBlock::matches (const void* dataToCompare, size_t dataSize) const noexcept
|
||||
{
|
||||
return size == dataSize
|
||||
&& memcmp (data, dataToCompare, size) == 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// this will resize the block to this size
|
||||
void MemoryBlock::setSize (const size_t newSize, const bool initialiseToZero)
|
||||
{
|
||||
if (size != newSize)
|
||||
{
|
||||
if (newSize <= 0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data != nullptr)
|
||||
{
|
||||
data.realloc (newSize);
|
||||
|
||||
if (initialiseToZero && (newSize > size))
|
||||
zeromem (data + size, newSize - size);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.allocate (newSize, initialiseToZero);
|
||||
}
|
||||
|
||||
size = newSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBlock::reset()
|
||||
{
|
||||
data.free();
|
||||
size = 0;
|
||||
}
|
||||
|
||||
void MemoryBlock::ensureSize (const size_t minimumSize, const bool initialiseToZero)
|
||||
{
|
||||
if (size < minimumSize)
|
||||
setSize (minimumSize, initialiseToZero);
|
||||
}
|
||||
|
||||
void MemoryBlock::swapWith (MemoryBlock& other) noexcept
|
||||
{
|
||||
std::swap (size, other.size);
|
||||
data.swapWith (other.data);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MemoryBlock::fillWith (const uint8 value) noexcept
|
||||
{
|
||||
memset (data, (int) value, size);
|
||||
}
|
||||
|
||||
void MemoryBlock::append (const void* const srcData, const size_t numBytes)
|
||||
{
|
||||
if (numBytes > 0)
|
||||
{
|
||||
jassert (srcData != nullptr); // this must not be null!
|
||||
const size_t oldSize = size;
|
||||
setSize (size + numBytes);
|
||||
memcpy (data + oldSize, srcData, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBlock::replaceWith (const void* const srcData, const size_t numBytes)
|
||||
{
|
||||
if (numBytes > 0)
|
||||
{
|
||||
jassert (srcData != nullptr); // this must not be null!
|
||||
setSize (numBytes);
|
||||
memcpy (data, srcData, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBlock::insert (const void* const srcData, const size_t numBytes, size_t insertPosition)
|
||||
{
|
||||
if (numBytes > 0)
|
||||
{
|
||||
jassert (srcData != nullptr); // this must not be null!
|
||||
insertPosition = jmin (size, insertPosition);
|
||||
const size_t trailingDataSize = size - insertPosition;
|
||||
setSize (size + numBytes, false);
|
||||
|
||||
if (trailingDataSize > 0)
|
||||
memmove (data + insertPosition + numBytes,
|
||||
data + insertPosition,
|
||||
trailingDataSize);
|
||||
|
||||
memcpy (data + insertPosition, srcData, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBlock::removeSection (const size_t startByte, const size_t numBytesToRemove)
|
||||
{
|
||||
if (startByte + numBytesToRemove >= size)
|
||||
{
|
||||
setSize (startByte);
|
||||
}
|
||||
else if (numBytesToRemove > 0)
|
||||
{
|
||||
memmove (data + startByte,
|
||||
data + startByte + numBytesToRemove,
|
||||
size - (startByte + numBytesToRemove));
|
||||
|
||||
setSize (size - numBytesToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryBlock::copyFrom (const void* const src, int offset, size_t num) noexcept
|
||||
{
|
||||
const char* d = static_cast<const char*> (src);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
d -= offset;
|
||||
num += (size_t) -offset;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if ((size_t) offset + num > size)
|
||||
num = size - (size_t) offset;
|
||||
|
||||
if (num > 0)
|
||||
memcpy (data + offset, d, num);
|
||||
}
|
||||
|
||||
void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcept
|
||||
{
|
||||
char* d = static_cast<char*> (dst);
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
zeromem (d, (size_t) -offset);
|
||||
d -= offset;
|
||||
num -= (size_t) -offset;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if ((size_t) offset + num > size)
|
||||
{
|
||||
const size_t newNum = size - (size_t) offset;
|
||||
zeromem (d + newNum, num - newNum);
|
||||
num = newNum;
|
||||
}
|
||||
|
||||
if (num > 0)
|
||||
memcpy (d, data + offset, num);
|
||||
}
|
||||
|
||||
String MemoryBlock::toString() const
|
||||
{
|
||||
return String::fromUTF8 (data, (int) size);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int MemoryBlock::getBitRange (const size_t bitRangeStart, size_t numBits) const noexcept
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
size_t byte = bitRangeStart >> 3;
|
||||
size_t offsetInByte = bitRangeStart & 7;
|
||||
size_t bitsSoFar = 0;
|
||||
|
||||
while (numBits > 0 && (size_t) byte < size)
|
||||
{
|
||||
const size_t bitsThisTime = jmin (numBits, 8 - offsetInByte);
|
||||
const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte;
|
||||
|
||||
res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar);
|
||||
|
||||
bitsSoFar += bitsThisTime;
|
||||
numBits -= bitsThisTime;
|
||||
++byte;
|
||||
offsetInByte = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int bitsToSet) noexcept
|
||||
{
|
||||
size_t byte = bitRangeStart >> 3;
|
||||
size_t offsetInByte = bitRangeStart & 7;
|
||||
uint32 mask = ~((((uint32) 0xffffffff) << (32 - numBits)) >> (32 - numBits));
|
||||
|
||||
while (numBits > 0 && (size_t) byte < size)
|
||||
{
|
||||
const size_t bitsThisTime = jmin (numBits, 8 - offsetInByte);
|
||||
|
||||
const uint32 tempMask = (mask << offsetInByte) | ~((((uint32) 0xffffffff) >> offsetInByte) << offsetInByte);
|
||||
const uint32 tempBits = (uint32) bitsToSet << offsetInByte;
|
||||
|
||||
data[byte] = (char) (((uint32) data[byte] & tempMask) | tempBits);
|
||||
|
||||
++byte;
|
||||
numBits -= bitsThisTime;
|
||||
bitsToSet >>= bitsThisTime;
|
||||
mask >>= bitsThisTime;
|
||||
offsetInByte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MemoryBlock::loadFromHexString (StringRef hex)
|
||||
{
|
||||
ensureSize ((size_t) hex.length() >> 1);
|
||||
char* dest = data;
|
||||
String::CharPointerType t (hex.text);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int byte = 0;
|
||||
|
||||
for (int loop = 2; --loop >= 0;)
|
||||
{
|
||||
byte <<= 4;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const juce_wchar c = t.getAndAdvance();
|
||||
|
||||
if (c >= '0' && c <= '9') { byte |= c - '0'; break; }
|
||||
if (c >= 'a' && c <= 'z') { byte |= c - ('a' - 10); break; }
|
||||
if (c >= 'A' && c <= 'Z') { byte |= c - ('A' - 10); break; }
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
setSize (static_cast<size_t> (dest - data));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*dest++ = (char) byte;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static const char base64EncodingTable[] = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";
|
||||
|
||||
String MemoryBlock::toBase64Encoding() const
|
||||
{
|
||||
const size_t numChars = ((size << 3) + 5) / 6;
|
||||
|
||||
String destString ((unsigned int) size); // store the length, followed by a '.', and then the data.
|
||||
const int initialLen = destString.length();
|
||||
destString.preallocateBytes (sizeof (String::CharPointerType::CharType) * (size_t) initialLen + 2 + numChars);
|
||||
|
||||
String::CharPointerType d (destString.getCharPointer());
|
||||
d += initialLen;
|
||||
d.write ('.');
|
||||
|
||||
for (size_t i = 0; i < numChars; ++i)
|
||||
d.write ((juce_wchar) (uint8) base64EncodingTable [getBitRange (i * 6, 6)]);
|
||||
|
||||
d.writeNull();
|
||||
return destString;
|
||||
}
|
||||
|
||||
static const char base64DecodingTable[] =
|
||||
{
|
||||
63, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
|
||||
0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52
|
||||
};
|
||||
|
||||
bool MemoryBlock::fromBase64Encoding (StringRef s)
|
||||
{
|
||||
String::CharPointerType dot (CharacterFunctions::find (s.text, (juce_wchar) '.'));
|
||||
|
||||
if (dot.isEmpty())
|
||||
return false;
|
||||
|
||||
const int numBytesNeeded = String (s.text, dot).getIntValue();
|
||||
|
||||
setSize ((size_t) numBytesNeeded, true);
|
||||
|
||||
String::CharPointerType srcChars (dot + 1);
|
||||
int pos = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int c = (int) srcChars.getAndAdvance();
|
||||
|
||||
if (c == 0)
|
||||
return true;
|
||||
|
||||
c -= 43;
|
||||
if (isPositiveAndBelow (c, numElementsInArray (base64DecodingTable)))
|
||||
{
|
||||
setBitRange ((size_t) pos, 6, base64DecodingTable [c]);
|
||||
pos += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_MEMORYBLOCK_H_INCLUDED
|
||||
#define JUCE_MEMORYBLOCK_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A class to hold a resizable block of raw data.
|
||||
|
||||
*/
|
||||
class JUCE_API MemoryBlock
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Create an uninitialised block with 0 size. */
|
||||
MemoryBlock() noexcept;
|
||||
|
||||
/** Creates a memory block with a given initial size.
|
||||
|
||||
@param initialSize the size of block to create
|
||||
@param initialiseToZero whether to clear the memory or just leave it uninitialised
|
||||
*/
|
||||
MemoryBlock (const size_t initialSize,
|
||||
bool initialiseToZero = false);
|
||||
|
||||
/** Creates a copy of another memory block. */
|
||||
MemoryBlock (const MemoryBlock&);
|
||||
|
||||
/** Creates a memory block using a copy of a block of data.
|
||||
|
||||
@param dataToInitialiseFrom some data to copy into this block
|
||||
@param sizeInBytes how much space to use
|
||||
*/
|
||||
MemoryBlock (const void* dataToInitialiseFrom, size_t sizeInBytes);
|
||||
|
||||
/** Destructor. */
|
||||
~MemoryBlock() noexcept;
|
||||
|
||||
/** Copies another memory block onto this one.
|
||||
This block will be resized and copied to exactly match the other one.
|
||||
*/
|
||||
MemoryBlock& operator= (const MemoryBlock&);
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
MemoryBlock (MemoryBlock&&) noexcept;
|
||||
MemoryBlock& operator= (MemoryBlock&&) noexcept;
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/** Compares two memory blocks.
|
||||
@returns true only if the two blocks are the same size and have identical contents.
|
||||
*/
|
||||
bool operator== (const MemoryBlock& other) const noexcept;
|
||||
|
||||
/** Compares two memory blocks.
|
||||
@returns true if the two blocks are different sizes or have different contents.
|
||||
*/
|
||||
bool operator!= (const MemoryBlock& other) const noexcept;
|
||||
|
||||
/** Returns true if the data in this MemoryBlock matches the raw bytes passed-in. */
|
||||
bool matches (const void* data, size_t dataSize) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a void pointer to the data.
|
||||
|
||||
Note that the pointer returned will probably become invalid when the
|
||||
block is resized.
|
||||
*/
|
||||
void* getData() const noexcept { return data; }
|
||||
|
||||
/** Returns a byte from the memory block.
|
||||
This returns a reference, so you can also use it to set a byte.
|
||||
*/
|
||||
template <typename Type>
|
||||
char& operator[] (const Type offset) const noexcept { return data [offset]; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the block's current allocated size, in bytes. */
|
||||
size_t getSize() const noexcept { return size; }
|
||||
|
||||
/** Resizes the memory block.
|
||||
|
||||
Any data that is present in both the old and new sizes will be retained.
|
||||
When enlarging the block, the new space that is allocated at the end can either be
|
||||
cleared, or left uninitialised.
|
||||
|
||||
@param newSize the new desired size for the block
|
||||
@param initialiseNewSpaceToZero if the block gets enlarged, this determines
|
||||
whether to clear the new section or just leave it
|
||||
uninitialised
|
||||
@see ensureSize
|
||||
*/
|
||||
void setSize (const size_t newSize,
|
||||
bool initialiseNewSpaceToZero = false);
|
||||
|
||||
/** Increases the block's size only if it's smaller than a given size.
|
||||
|
||||
@param minimumSize if the block is already bigger than this size, no action
|
||||
will be taken; otherwise it will be increased to this size
|
||||
@param initialiseNewSpaceToZero if the block gets enlarged, this determines
|
||||
whether to clear the new section or just leave it
|
||||
uninitialised
|
||||
@see setSize
|
||||
*/
|
||||
void ensureSize (const size_t minimumSize,
|
||||
bool initialiseNewSpaceToZero = false);
|
||||
|
||||
/** Frees all the blocks data, setting its size to 0. */
|
||||
void reset();
|
||||
|
||||
//==============================================================================
|
||||
/** Fills the entire memory block with a repeated byte value.
|
||||
This is handy for clearing a block of memory to zero.
|
||||
*/
|
||||
void fillWith (uint8 valueToUse) noexcept;
|
||||
|
||||
/** Adds another block of data to the end of this one.
|
||||
The data pointer must not be null. This block's size will be increased accordingly.
|
||||
*/
|
||||
void append (const void* data, size_t numBytes);
|
||||
|
||||
/** Resizes this block to the given size and fills its contents from the supplied buffer.
|
||||
The data pointer must not be null.
|
||||
*/
|
||||
void replaceWith (const void* data, size_t numBytes);
|
||||
|
||||
/** Inserts some data into the block.
|
||||
The dataToInsert pointer must not be null. This block's size will be increased accordingly.
|
||||
If the insert position lies outside the valid range of the block, it will be clipped to
|
||||
within the range before being used.
|
||||
*/
|
||||
void insert (const void* dataToInsert, size_t numBytesToInsert, size_t insertPosition);
|
||||
|
||||
/** Chops out a section of the block.
|
||||
|
||||
This will remove a section of the memory block and close the gap around it,
|
||||
shifting any subsequent data downwards and reducing the size of the block.
|
||||
|
||||
If the range specified goes beyond the size of the block, it will be clipped.
|
||||
*/
|
||||
void removeSection (size_t startByte, size_t numBytesToRemove);
|
||||
|
||||
//==============================================================================
|
||||
/** Copies data into this MemoryBlock from a memory address.
|
||||
|
||||
@param srcData the memory location of the data to copy into this block
|
||||
@param destinationOffset the offset in this block at which the data being copied should begin
|
||||
@param numBytes how much to copy in (if this goes beyond the size of the memory block,
|
||||
it will be clipped so not to do anything nasty)
|
||||
*/
|
||||
void copyFrom (const void* srcData,
|
||||
int destinationOffset,
|
||||
size_t numBytes) noexcept;
|
||||
|
||||
/** Copies data from this MemoryBlock to a memory address.
|
||||
|
||||
@param destData the memory location to write to
|
||||
@param sourceOffset the offset within this block from which the copied data will be read
|
||||
@param numBytes how much to copy (if this extends beyond the limits of the memory block,
|
||||
zeros will be used for that portion of the data)
|
||||
*/
|
||||
void copyTo (void* destData,
|
||||
int sourceOffset,
|
||||
size_t numBytes) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Exchanges the contents of this and another memory block.
|
||||
No actual copying is required for this, so it's very fast.
|
||||
*/
|
||||
void swapWith (MemoryBlock& other) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Attempts to parse the contents of the block as a zero-terminated UTF8 string. */
|
||||
String toString() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Parses a string of hexadecimal numbers and writes this data into the memory block.
|
||||
|
||||
The block will be resized to the number of valid bytes read from the string.
|
||||
Non-hex characters in the string will be ignored.
|
||||
|
||||
@see String::toHexString()
|
||||
*/
|
||||
void loadFromHexString (StringRef sourceHexString);
|
||||
|
||||
//==============================================================================
|
||||
/** Sets a number of bits in the memory block, treating it as a long binary sequence. */
|
||||
void setBitRange (size_t bitRangeStart,
|
||||
size_t numBits,
|
||||
int binaryNumberToApply) noexcept;
|
||||
|
||||
/** Reads a number of bits from the memory block, treating it as one long binary sequence */
|
||||
int getBitRange (size_t bitRangeStart,
|
||||
size_t numBitsToRead) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a string of characters that represent the binary contents of this block.
|
||||
|
||||
Uses a 64-bit encoding system to allow binary data to be turned into a string
|
||||
of simple non-extended characters, e.g. for storage in XML.
|
||||
|
||||
@see fromBase64Encoding
|
||||
*/
|
||||
String toBase64Encoding() const;
|
||||
|
||||
/** Takes a string of encoded characters and turns it into binary data.
|
||||
|
||||
The string passed in must have been created by to64BitEncoding(), and this
|
||||
block will be resized to recreate the original data block.
|
||||
|
||||
@see toBase64Encoding
|
||||
*/
|
||||
bool fromBase64Encoding (StringRef encodedString);
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
HeapBlock<char> data;
|
||||
size_t size;
|
||||
|
||||
JUCE_LEAK_DETECTOR (MemoryBlock)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_MEMORYBLOCK_H_INCLUDED
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_OPTIONALSCOPEDPOINTER_H_INCLUDED
|
||||
#define JUCE_OPTIONALSCOPEDPOINTER_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Holds a pointer to an object which can optionally be deleted when this pointer
|
||||
goes out of scope.
|
||||
|
||||
This acts in many ways like a ScopedPointer, but allows you to specify whether or
|
||||
not the object is deleted.
|
||||
|
||||
@see ScopedPointer
|
||||
*/
|
||||
template <class ObjectType>
|
||||
class OptionalScopedPointer
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty OptionalScopedPointer. */
|
||||
OptionalScopedPointer() : shouldDelete (false) {}
|
||||
|
||||
/** Creates an OptionalScopedPointer to point to a given object, and specifying whether
|
||||
the OptionalScopedPointer will delete it.
|
||||
|
||||
If takeOwnership is true, then the OptionalScopedPointer will act like a ScopedPointer,
|
||||
deleting the object when it is itself deleted. If this parameter is false, then the
|
||||
OptionalScopedPointer just holds a normal pointer to the object, and won't delete it.
|
||||
*/
|
||||
OptionalScopedPointer (ObjectType* objectToHold, bool takeOwnership)
|
||||
: object (objectToHold), shouldDelete (takeOwnership)
|
||||
{
|
||||
}
|
||||
|
||||
/** Takes ownership of the object that another OptionalScopedPointer holds.
|
||||
|
||||
Like a normal ScopedPointer, the objectToTransferFrom object will become null,
|
||||
as ownership of the managed object is transferred to this object.
|
||||
|
||||
The flag to indicate whether or not to delete the managed object is also
|
||||
copied from the source object.
|
||||
*/
|
||||
OptionalScopedPointer (OptionalScopedPointer& objectToTransferFrom)
|
||||
: object (objectToTransferFrom.release()),
|
||||
shouldDelete (objectToTransferFrom.shouldDelete)
|
||||
{
|
||||
}
|
||||
|
||||
/** Takes ownership of the object that another OptionalScopedPointer holds.
|
||||
|
||||
Like a normal ScopedPointer, the objectToTransferFrom object will become null,
|
||||
as ownership of the managed object is transferred to this object.
|
||||
|
||||
The ownership flag that says whether or not to delete the managed object is also
|
||||
copied from the source object.
|
||||
*/
|
||||
OptionalScopedPointer& operator= (OptionalScopedPointer& objectToTransferFrom)
|
||||
{
|
||||
if (object != objectToTransferFrom.object)
|
||||
{
|
||||
clear();
|
||||
object = objectToTransferFrom.object;
|
||||
}
|
||||
|
||||
shouldDelete = objectToTransferFrom.shouldDelete;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** The destructor may or may not delete the object that is being held, depending on the
|
||||
takeOwnership flag that was specified when the object was first passed into an
|
||||
OptionalScopedPointer constructor.
|
||||
*/
|
||||
~OptionalScopedPointer()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the object that this pointer is managing. */
|
||||
inline operator ObjectType*() const noexcept { return object; }
|
||||
|
||||
/** Returns the object that this pointer is managing. */
|
||||
inline ObjectType* get() const noexcept { return object; }
|
||||
|
||||
/** Returns the object that this pointer is managing. */
|
||||
inline ObjectType& operator*() const noexcept { return *object; }
|
||||
|
||||
/** Lets you access methods and properties of the object that this pointer is holding. */
|
||||
inline ObjectType* operator->() const noexcept { return object; }
|
||||
|
||||
//==============================================================================
|
||||
/** Removes the current object from this OptionalScopedPointer without deleting it.
|
||||
This will return the current object, and set this OptionalScopedPointer to a null pointer.
|
||||
*/
|
||||
ObjectType* release() noexcept { return object.release(); }
|
||||
|
||||
/** Resets this pointer to null, possibly deleting the object that it holds, if it has
|
||||
ownership of it.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
if (! shouldDelete)
|
||||
object.release();
|
||||
}
|
||||
|
||||
/** Makes this OptionalScopedPointer point at a new object, specifying whether the
|
||||
OptionalScopedPointer will take ownership of the object.
|
||||
|
||||
If takeOwnership is true, then the OptionalScopedPointer will act like a ScopedPointer,
|
||||
deleting the object when it is itself deleted. If this parameter is false, then the
|
||||
OptionalScopedPointer just holds a normal pointer to the object, and won't delete it.
|
||||
*/
|
||||
void set (ObjectType* newObject, bool takeOwnership)
|
||||
{
|
||||
if (object != newObject)
|
||||
{
|
||||
clear();
|
||||
object = newObject;
|
||||
}
|
||||
|
||||
shouldDelete = takeOwnership;
|
||||
}
|
||||
|
||||
/** Makes this OptionalScopedPointer point at a new object, and take ownership of that object. */
|
||||
void setOwned (ObjectType* newObject)
|
||||
{
|
||||
set (newObject, true);
|
||||
}
|
||||
|
||||
/** Makes this OptionalScopedPointer point at a new object, but will not take ownership of that object. */
|
||||
void setNonOwned (ObjectType* newObject)
|
||||
{
|
||||
set (newObject, false);
|
||||
}
|
||||
|
||||
/** Returns true if the target object will be deleted when this pointer
|
||||
object is deleted.
|
||||
*/
|
||||
bool willDeleteObject() const noexcept { return shouldDelete; }
|
||||
|
||||
//==============================================================================
|
||||
/** Swaps this object with another OptionalScopedPointer.
|
||||
The two objects simply exchange their states.
|
||||
*/
|
||||
void swapWith (OptionalScopedPointer<ObjectType>& other) noexcept
|
||||
{
|
||||
object.swapWith (other.object);
|
||||
std::swap (shouldDelete, other.shouldDelete);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
ScopedPointer<ObjectType> object;
|
||||
bool shouldDelete;
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_OPTIONALSCOPEDPOINTER_H_INCLUDED
|
||||
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_REFERENCECOUNTEDOBJECT_H_INCLUDED
|
||||
#define JUCE_REFERENCECOUNTEDOBJECT_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A base class which provides methods for reference-counting.
|
||||
|
||||
To add reference-counting to a class, derive it from this class, and
|
||||
use the ReferenceCountedObjectPtr class to point to it.
|
||||
|
||||
e.g. @code
|
||||
class MyClass : public ReferenceCountedObject
|
||||
{
|
||||
void foo();
|
||||
|
||||
// This is a neat way of declaring a typedef for a pointer class,
|
||||
// rather than typing out the full templated name each time..
|
||||
typedef ReferenceCountedObjectPtr<MyClass> Ptr;
|
||||
};
|
||||
|
||||
MyClass::Ptr p = new MyClass();
|
||||
MyClass::Ptr p2 = p;
|
||||
p = nullptr;
|
||||
p2->foo();
|
||||
@endcode
|
||||
|
||||
Once a new ReferenceCountedObject has been assigned to a pointer, be
|
||||
careful not to delete the object manually.
|
||||
|
||||
This class uses an Atomic<int> value to hold the reference count, so that it
|
||||
the pointers can be passed between threads safely. For a faster but non-thread-safe
|
||||
version, use SingleThreadedReferenceCountedObject instead.
|
||||
|
||||
@see ReferenceCountedObjectPtr, ReferenceCountedArray, SingleThreadedReferenceCountedObject
|
||||
*/
|
||||
class JUCE_API ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Increments the object's reference count.
|
||||
|
||||
This is done automatically by the smart pointer, but is public just
|
||||
in case it's needed for nefarious purposes.
|
||||
*/
|
||||
void incReferenceCount() noexcept
|
||||
{
|
||||
++refCount;
|
||||
}
|
||||
|
||||
/** Decreases the object's reference count.
|
||||
If the count gets to zero, the object will be deleted.
|
||||
*/
|
||||
void decReferenceCount() noexcept
|
||||
{
|
||||
jassert (getReferenceCount() > 0);
|
||||
|
||||
if (--refCount == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
/** Decreases the object's reference count.
|
||||
If the count gets to zero, the object will not be deleted, but this method
|
||||
will return true, allowing the caller to take care of deletion.
|
||||
*/
|
||||
bool decReferenceCountWithoutDeleting() noexcept
|
||||
{
|
||||
jassert (getReferenceCount() > 0);
|
||||
return --refCount == 0;
|
||||
}
|
||||
|
||||
/** Returns the object's current reference count. */
|
||||
int getReferenceCount() const noexcept { return refCount.get(); }
|
||||
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates the reference-counted object (with an initial ref count of zero). */
|
||||
ReferenceCountedObject() {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~ReferenceCountedObject()
|
||||
{
|
||||
// it's dangerous to delete an object that's still referenced by something else!
|
||||
jassert (getReferenceCount() == 0);
|
||||
}
|
||||
|
||||
/** Resets the reference count to zero without deleting the object.
|
||||
You should probably never need to use this!
|
||||
*/
|
||||
void resetReferenceCount() noexcept
|
||||
{
|
||||
refCount = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Atomic <int> refCount;
|
||||
|
||||
friend struct ContainerDeletePolicy<ReferenceCountedObject>;
|
||||
JUCE_DECLARE_NON_COPYABLE (ReferenceCountedObject)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Adds reference-counting to an object.
|
||||
|
||||
This is effectively a version of the ReferenceCountedObject class, but which
|
||||
uses a non-atomic counter, and so is not thread-safe (but which will be more
|
||||
efficient).
|
||||
For more details on how to use it, see the ReferenceCountedObject class notes.
|
||||
|
||||
@see ReferenceCountedObject, ReferenceCountedObjectPtr, ReferenceCountedArray
|
||||
*/
|
||||
class JUCE_API SingleThreadedReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Increments the object's reference count.
|
||||
|
||||
This is done automatically by the smart pointer, but is public just
|
||||
in case it's needed for nefarious purposes.
|
||||
*/
|
||||
void incReferenceCount() noexcept
|
||||
{
|
||||
++refCount;
|
||||
}
|
||||
|
||||
/** Decreases the object's reference count.
|
||||
If the count gets to zero, the object will be deleted.
|
||||
*/
|
||||
void decReferenceCount() noexcept
|
||||
{
|
||||
jassert (getReferenceCount() > 0);
|
||||
|
||||
if (--refCount == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
/** Decreases the object's reference count.
|
||||
If the count gets to zero, the object will not be deleted, but this method
|
||||
will return true, allowing the caller to take care of deletion.
|
||||
*/
|
||||
bool decReferenceCountWithoutDeleting() noexcept
|
||||
{
|
||||
jassert (getReferenceCount() > 0);
|
||||
return --refCount == 0;
|
||||
}
|
||||
|
||||
/** Returns the object's current reference count. */
|
||||
int getReferenceCount() const noexcept { return refCount; }
|
||||
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates the reference-counted object (with an initial ref count of zero). */
|
||||
SingleThreadedReferenceCountedObject() : refCount (0) {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~SingleThreadedReferenceCountedObject()
|
||||
{
|
||||
// it's dangerous to delete an object that's still referenced by something else!
|
||||
jassert (getReferenceCount() == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
int refCount;
|
||||
|
||||
friend struct ContainerDeletePolicy<ReferenceCountedObject>;
|
||||
JUCE_DECLARE_NON_COPYABLE (SingleThreadedReferenceCountedObject)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A smart-pointer class which points to a reference-counted object.
|
||||
|
||||
The template parameter specifies the class of the object you want to point to - the easiest
|
||||
way to make a class reference-countable is to simply make it inherit from ReferenceCountedObject
|
||||
or SingleThreadedReferenceCountedObject, but if you need to, you can roll your own reference-countable
|
||||
class by implementing a set of methods called incReferenceCount(), decReferenceCount(), and
|
||||
decReferenceCountWithoutDeleting(). See ReferenceCountedObject for examples of how these methods
|
||||
should behave.
|
||||
|
||||
When using this class, you'll probably want to create a typedef to abbreviate the full
|
||||
templated name - e.g.
|
||||
@code
|
||||
struct MyClass : public ReferenceCountedObject
|
||||
{
|
||||
typedef ReferenceCountedObjectPtr<MyClass> Ptr;
|
||||
...
|
||||
@endcode
|
||||
|
||||
@see ReferenceCountedObject, ReferenceCountedObjectArray
|
||||
*/
|
||||
template <class ReferenceCountedObjectClass>
|
||||
class ReferenceCountedObjectPtr
|
||||
{
|
||||
public:
|
||||
/** The class being referenced by this pointer. */
|
||||
typedef ReferenceCountedObjectClass ReferencedType;
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a pointer to a null object. */
|
||||
ReferenceCountedObjectPtr() noexcept
|
||||
: referencedObject (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a pointer to an object.
|
||||
This will increment the object's reference-count.
|
||||
*/
|
||||
ReferenceCountedObjectPtr (ReferencedType* refCountedObject) noexcept
|
||||
: referencedObject (refCountedObject)
|
||||
{
|
||||
incIfNotNull (refCountedObject);
|
||||
}
|
||||
|
||||
/** Copies another pointer.
|
||||
This will increment the object's reference-count.
|
||||
*/
|
||||
ReferenceCountedObjectPtr (const ReferenceCountedObjectPtr& other) noexcept
|
||||
: referencedObject (other.referencedObject)
|
||||
{
|
||||
incIfNotNull (referencedObject);
|
||||
}
|
||||
|
||||
/** Copies another pointer.
|
||||
This will increment the object's reference-count (if it is non-null).
|
||||
*/
|
||||
template <class Convertible>
|
||||
ReferenceCountedObjectPtr (const ReferenceCountedObjectPtr<Convertible>& other) noexcept
|
||||
: referencedObject (static_cast <ReferencedType*> (other.get()))
|
||||
{
|
||||
incIfNotNull (referencedObject);
|
||||
}
|
||||
|
||||
/** Changes this pointer to point at a different object.
|
||||
The reference count of the old object is decremented, and it might be
|
||||
deleted if it hits zero. The new object's count is incremented.
|
||||
*/
|
||||
ReferenceCountedObjectPtr& operator= (const ReferenceCountedObjectPtr& other)
|
||||
{
|
||||
return operator= (other.referencedObject);
|
||||
}
|
||||
|
||||
/** Changes this pointer to point at a different object.
|
||||
The reference count of the old object is decremented, and it might be
|
||||
deleted if it hits zero. The new object's count is incremented.
|
||||
*/
|
||||
template <class Convertible>
|
||||
ReferenceCountedObjectPtr& operator= (const ReferenceCountedObjectPtr<Convertible>& other)
|
||||
{
|
||||
return operator= (static_cast<ReferencedType*> (other.get()));
|
||||
}
|
||||
|
||||
/** Changes this pointer to point at a different object.
|
||||
|
||||
The reference count of the old object is decremented, and it might be
|
||||
deleted if it hits zero. The new object's count is incremented.
|
||||
*/
|
||||
ReferenceCountedObjectPtr& operator= (ReferencedType* const newObject)
|
||||
{
|
||||
if (referencedObject != newObject)
|
||||
{
|
||||
incIfNotNull (newObject);
|
||||
ReferencedType* const oldObject = referencedObject;
|
||||
referencedObject = newObject;
|
||||
decIfNotNull (oldObject);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
/** Takes-over the object from another pointer. */
|
||||
ReferenceCountedObjectPtr (ReferenceCountedObjectPtr&& other) noexcept
|
||||
: referencedObject (other.referencedObject)
|
||||
{
|
||||
other.referencedObject = nullptr;
|
||||
}
|
||||
|
||||
/** Takes-over the object from another pointer. */
|
||||
ReferenceCountedObjectPtr& operator= (ReferenceCountedObjectPtr&& other)
|
||||
{
|
||||
std::swap (referencedObject, other.referencedObject);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Destructor.
|
||||
This will decrement the object's reference-count, which will cause the
|
||||
object to be deleted when the ref-count hits zero.
|
||||
*/
|
||||
~ReferenceCountedObjectPtr()
|
||||
{
|
||||
decIfNotNull (referencedObject);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the object that this pointer references.
|
||||
The pointer returned may be null, of course.
|
||||
*/
|
||||
operator ReferencedType*() const noexcept { return referencedObject; }
|
||||
|
||||
/** Returns the object that this pointer references.
|
||||
The pointer returned may be null, of course.
|
||||
*/
|
||||
ReferencedType* get() const noexcept { return referencedObject; }
|
||||
|
||||
/** Returns the object that this pointer references.
|
||||
The pointer returned may be null, of course.
|
||||
*/
|
||||
ReferencedType* getObject() const noexcept { return referencedObject; }
|
||||
|
||||
// the -> operator is called on the referenced object
|
||||
ReferencedType* operator->() const noexcept
|
||||
{
|
||||
jassert (referencedObject != nullptr); // null pointer method call!
|
||||
return referencedObject;
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
ReferencedType* referencedObject;
|
||||
|
||||
static void incIfNotNull (ReferencedType* o) noexcept
|
||||
{
|
||||
if (o != nullptr)
|
||||
o->incReferenceCount();
|
||||
}
|
||||
|
||||
static void decIfNotNull (ReferencedType* o) noexcept
|
||||
{
|
||||
if (o != nullptr && o->decReferenceCountWithoutDeleting())
|
||||
ContainerDeletePolicy<ReferencedType>::destroy (o);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Compares two ReferenceCountedObjectPointers. */
|
||||
template <class ReferenceCountedObjectClass>
|
||||
bool operator== (const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object1, ReferenceCountedObjectClass* const object2) noexcept
|
||||
{
|
||||
return object1.get() == object2;
|
||||
}
|
||||
|
||||
/** Compares two ReferenceCountedObjectPointers. */
|
||||
template <class ReferenceCountedObjectClass>
|
||||
bool operator== (const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object2) noexcept
|
||||
{
|
||||
return object1.get() == object2.get();
|
||||
}
|
||||
|
||||
/** Compares two ReferenceCountedObjectPointers. */
|
||||
template <class ReferenceCountedObjectClass>
|
||||
bool operator== (ReferenceCountedObjectClass* object1, const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object2) noexcept
|
||||
{
|
||||
return object1 == object2.get();
|
||||
}
|
||||
|
||||
/** Compares two ReferenceCountedObjectPointers. */
|
||||
template <class ReferenceCountedObjectClass>
|
||||
bool operator!= (const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectClass* object2) noexcept
|
||||
{
|
||||
return object1.get() != object2;
|
||||
}
|
||||
|
||||
/** Compares two ReferenceCountedObjectPointers. */
|
||||
template <class ReferenceCountedObjectClass>
|
||||
bool operator!= (const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object2) noexcept
|
||||
{
|
||||
return object1.get() != object2.get();
|
||||
}
|
||||
|
||||
/** Compares two ReferenceCountedObjectPointers. */
|
||||
template <class ReferenceCountedObjectClass>
|
||||
bool operator!= (ReferenceCountedObjectClass* object1, const ReferenceCountedObjectPtr<ReferenceCountedObjectClass>& object2) noexcept
|
||||
{
|
||||
return object1 != object2.get();
|
||||
}
|
||||
|
||||
|
||||
#endif // JUCE_REFERENCECOUNTEDOBJECT_H_INCLUDED
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_SCOPEDPOINTER_H_INCLUDED
|
||||
#define JUCE_SCOPEDPOINTER_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
This class holds a pointer which is automatically deleted when this object goes
|
||||
out of scope.
|
||||
|
||||
Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer
|
||||
gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or
|
||||
as member variables is a good way to use RAII to avoid accidentally leaking dynamically
|
||||
created objects.
|
||||
|
||||
A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer
|
||||
to an object. If you use the assignment operator to assign a different object to a
|
||||
ScopedPointer, the old one will be automatically deleted.
|
||||
|
||||
Important note: The class is designed to hold a pointer to an object, NOT to an array!
|
||||
It calls delete on its payload, not delete[], so do not give it an array to hold! For
|
||||
that kind of purpose, you should be using HeapBlock or Array instead.
|
||||
|
||||
A const ScopedPointer is guaranteed not to lose ownership of its object or change the
|
||||
object to which it points during its lifetime. This means that making a copy of a const
|
||||
ScopedPointer is impossible, as that would involve the new copy taking ownership from the
|
||||
old one.
|
||||
|
||||
If you need to get a pointer out of a ScopedPointer without it being deleted, you
|
||||
can use the release() method.
|
||||
|
||||
Something to note is the main difference between this class and the std::auto_ptr class,
|
||||
which is that ScopedPointer provides a cast-to-object operator, wheras std::auto_ptr
|
||||
requires that you always call get() to retrieve the pointer. The advantages of providing
|
||||
the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much
|
||||
exactly the same way as a raw pointer. The disadvantage is that the compiler is free to
|
||||
use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult
|
||||
to return a ScopedPointer as the result of a function. To avoid this causing errors,
|
||||
ScopedPointer contains an overloaded constructor that should cause a syntax error in these
|
||||
circumstances, but it does mean that instead of returning a ScopedPointer from a function,
|
||||
you'd need to return a raw pointer (or use a std::auto_ptr instead).
|
||||
*/
|
||||
template <class ObjectType>
|
||||
class ScopedPointer
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a ScopedPointer containing a null pointer. */
|
||||
inline ScopedPointer() noexcept : object (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a ScopedPointer that owns the specified object. */
|
||||
inline ScopedPointer (ObjectType* const objectToTakePossessionOf) noexcept
|
||||
: object (objectToTakePossessionOf)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a ScopedPointer that takes its pointer from another ScopedPointer.
|
||||
|
||||
Because a pointer can only belong to one ScopedPointer, this transfers
|
||||
the pointer from the other object to this one, and the other object is reset to
|
||||
be a null pointer.
|
||||
*/
|
||||
ScopedPointer (ScopedPointer& objectToTransferFrom) noexcept
|
||||
: object (objectToTransferFrom.object)
|
||||
{
|
||||
objectToTransferFrom.object = nullptr;
|
||||
}
|
||||
|
||||
/** Destructor.
|
||||
This will delete the object that this ScopedPointer currently refers to.
|
||||
*/
|
||||
inline ~ScopedPointer() { ContainerDeletePolicy<ObjectType>::destroy (object); }
|
||||
|
||||
/** Changes this ScopedPointer to point to a new object.
|
||||
|
||||
Because a pointer can only belong to one ScopedPointer, this transfers
|
||||
the pointer from the other object to this one, and the other object is reset to
|
||||
be a null pointer.
|
||||
|
||||
If this ScopedPointer already points to an object, that object
|
||||
will first be deleted.
|
||||
*/
|
||||
ScopedPointer& operator= (ScopedPointer& objectToTransferFrom)
|
||||
{
|
||||
if (this != objectToTransferFrom.getAddress())
|
||||
{
|
||||
// Two ScopedPointers should never be able to refer to the same object - if
|
||||
// this happens, you must have done something dodgy!
|
||||
jassert (object == nullptr || object != objectToTransferFrom.object);
|
||||
|
||||
ObjectType* const oldObject = object;
|
||||
object = objectToTransferFrom.object;
|
||||
objectToTransferFrom.object = nullptr;
|
||||
ContainerDeletePolicy<ObjectType>::destroy (oldObject);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Changes this ScopedPointer to point to a new object.
|
||||
|
||||
If this ScopedPointer already points to an object, that object
|
||||
will first be deleted.
|
||||
|
||||
The pointer that you pass in may be a nullptr.
|
||||
*/
|
||||
ScopedPointer& operator= (ObjectType* const newObjectToTakePossessionOf)
|
||||
{
|
||||
if (object != newObjectToTakePossessionOf)
|
||||
{
|
||||
ObjectType* const oldObject = object;
|
||||
object = newObjectToTakePossessionOf;
|
||||
ContainerDeletePolicy<ObjectType>::destroy (oldObject);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
ScopedPointer (ScopedPointer&& other) noexcept
|
||||
: object (other.object)
|
||||
{
|
||||
other.object = nullptr;
|
||||
}
|
||||
|
||||
ScopedPointer& operator= (ScopedPointer&& other) noexcept
|
||||
{
|
||||
object = other.object;
|
||||
other.object = nullptr;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the object that this ScopedPointer refers to. */
|
||||
inline operator ObjectType*() const noexcept { return object; }
|
||||
|
||||
/** Returns the object that this ScopedPointer refers to. */
|
||||
inline ObjectType* get() const noexcept { return object; }
|
||||
|
||||
/** Returns the object that this ScopedPointer refers to. */
|
||||
inline ObjectType& operator*() const noexcept { return *object; }
|
||||
|
||||
/** Lets you access methods and properties of the object that this ScopedPointer refers to. */
|
||||
inline ObjectType* operator->() const noexcept { return object; }
|
||||
|
||||
//==============================================================================
|
||||
/** Removes the current object from this ScopedPointer without deleting it.
|
||||
This will return the current object, and set the ScopedPointer to a null pointer.
|
||||
*/
|
||||
ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; }
|
||||
|
||||
//==============================================================================
|
||||
/** Swaps this object with that of another ScopedPointer.
|
||||
The two objects simply exchange their pointers.
|
||||
*/
|
||||
void swapWith (ScopedPointer<ObjectType>& other) noexcept
|
||||
{
|
||||
// Two ScopedPointers should never be able to refer to the same object - if
|
||||
// this happens, you must have done something dodgy!
|
||||
jassert (object != other.object || this == other.getAddress() || object == nullptr);
|
||||
|
||||
std::swap (object, other.object);
|
||||
}
|
||||
|
||||
/** If the pointer is non-null, this will attempt to return a new copy of the object that is pointed to.
|
||||
If the pointer is null, this will safely return a nullptr.
|
||||
*/
|
||||
inline ObjectType* createCopy() const { return createCopyIfNotNull (object); }
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
ObjectType* object;
|
||||
|
||||
// (Required as an alternative to the overloaded & operator).
|
||||
const ScopedPointer* getAddress() const noexcept { return this; }
|
||||
|
||||
#if ! JUCE_MSVC // (MSVC can't deal with multiple copy constructors)
|
||||
/* The copy constructors are private to stop people accidentally copying a const ScopedPointer
|
||||
(the compiler would let you do so by implicitly casting the source to its raw object pointer).
|
||||
|
||||
A side effect of this is that in a compiler that doesn't support C++11, you may hit an
|
||||
error when you write something like this:
|
||||
|
||||
ScopedPointer<MyClass> m = new MyClass(); // Compile error: copy constructor is private.
|
||||
|
||||
Even though the compiler would normally ignore the assignment here, it can't do so when the
|
||||
copy constructor is private. It's very easy to fix though - just write it like this:
|
||||
|
||||
ScopedPointer<MyClass> m (new MyClass()); // Compiles OK
|
||||
|
||||
It's probably best to use the latter form when writing your object declarations anyway, as
|
||||
this is a better representation of the code that you actually want the compiler to produce.
|
||||
*/
|
||||
JUCE_DECLARE_NON_COPYABLE (ScopedPointer)
|
||||
#endif
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Compares a ScopedPointer with another pointer.
|
||||
This can be handy for checking whether this is a null pointer.
|
||||
*/
|
||||
template <class ObjectType>
|
||||
bool operator== (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
|
||||
{
|
||||
return static_cast<ObjectType*> (pointer1) == pointer2;
|
||||
}
|
||||
|
||||
/** Compares a ScopedPointer with another pointer.
|
||||
This can be handy for checking whether this is a null pointer.
|
||||
*/
|
||||
template <class ObjectType>
|
||||
bool operator!= (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
|
||||
{
|
||||
return static_cast<ObjectType*> (pointer1) != pointer2;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#ifndef DOXYGEN
|
||||
// NB: This is just here to prevent any silly attempts to call deleteAndZero() on a ScopedPointer.
|
||||
template <typename Type>
|
||||
void deleteAndZero (ScopedPointer<Type>&) { static_jassert (sizeof (Type) == 12345); }
|
||||
#endif
|
||||
|
||||
#endif // JUCE_SCOPEDPOINTER_H_INCLUDED
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED
|
||||
#define JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A smart-pointer that automatically creates and manages the lifetime of a
|
||||
shared static instance of a class.
|
||||
|
||||
The SharedObjectType template type indicates the class to use for the shared
|
||||
object - the only requirements on this class are that it must have a public
|
||||
default constructor and destructor.
|
||||
|
||||
The SharedResourcePointer offers a pattern that differs from using a singleton or
|
||||
static instance of an object, because it uses reference-counting to make sure that
|
||||
the underlying shared object is automatically created/destroyed according to the
|
||||
number of SharedResourcePointer objects that exist. When the last one is deleted,
|
||||
the underlying object is also immediately destroyed. This allows you to use scoping
|
||||
to manage the lifetime of a shared resource.
|
||||
|
||||
Note: the construction/deletion of the shared object must not involve any
|
||||
code that makes recursive calls to a SharedResourcePointer, or you'll cause
|
||||
a deadlock.
|
||||
|
||||
Example:
|
||||
@code
|
||||
// An example of a class that contains the shared data you want to use.
|
||||
struct MySharedData
|
||||
{
|
||||
// There's no need to ever create an instance of this class directly yourself,
|
||||
// but it does need a public constructor that does the initialisation.
|
||||
MySharedData()
|
||||
{
|
||||
sharedStuff = generateHeavyweightStuff();
|
||||
}
|
||||
|
||||
Array<SomeKindOfData> sharedStuff;
|
||||
};
|
||||
|
||||
struct DataUserClass
|
||||
{
|
||||
DataUserClass()
|
||||
{
|
||||
// Multiple instances of the DataUserClass will all have the same
|
||||
// shared common instance of MySharedData referenced by their sharedData
|
||||
// member variables.
|
||||
useSharedStuff (sharedData->sharedStuff);
|
||||
}
|
||||
|
||||
// By keeping this pointer as a member variable, the shared resource
|
||||
// is guaranteed to be available for as long as the DataUserClass object.
|
||||
SharedResourcePointer<MySharedData> sharedData;
|
||||
};
|
||||
|
||||
@endcode
|
||||
*/
|
||||
template <typename SharedObjectType>
|
||||
class SharedResourcePointer
|
||||
{
|
||||
public:
|
||||
/** Creates an instance of the shared object.
|
||||
If other SharedResourcePointer objects for this type already exist, then
|
||||
this one will simply point to the same shared object that they are already
|
||||
using. Otherwise, if this is the first SharedResourcePointer to be created,
|
||||
then a shared object will be created automatically.
|
||||
*/
|
||||
SharedResourcePointer()
|
||||
{
|
||||
SharedObjectHolder& holder = getSharedObjectHolder();
|
||||
const SpinLock::ScopedLockType sl (holder.lock);
|
||||
|
||||
if (++(holder.refCount) == 1)
|
||||
holder.sharedInstance = new SharedObjectType();
|
||||
|
||||
sharedObject = holder.sharedInstance;
|
||||
}
|
||||
|
||||
/** Destructor.
|
||||
If no other SharedResourcePointer objects exist, this will also delete
|
||||
the shared object to which it refers.
|
||||
*/
|
||||
~SharedResourcePointer()
|
||||
{
|
||||
SharedObjectHolder& holder = getSharedObjectHolder();
|
||||
const SpinLock::ScopedLockType sl (holder.lock);
|
||||
|
||||
if (--(holder.refCount) == 0)
|
||||
holder.sharedInstance = nullptr;
|
||||
}
|
||||
|
||||
/** Returns the shared object. */
|
||||
operator SharedObjectType*() const noexcept { return sharedObject; }
|
||||
|
||||
/** Returns the shared object. */
|
||||
SharedObjectType& get() const noexcept { return *sharedObject; }
|
||||
|
||||
/** Returns the object that this pointer references.
|
||||
The pointer returned may be zero, of course.
|
||||
*/
|
||||
SharedObjectType& getObject() const noexcept { return *sharedObject; }
|
||||
|
||||
SharedObjectType* operator->() const noexcept { return sharedObject; }
|
||||
|
||||
private:
|
||||
struct SharedObjectHolder : public ReferenceCountedObject
|
||||
{
|
||||
SpinLock lock;
|
||||
ScopedPointer<SharedObjectType> sharedInstance;
|
||||
int refCount;
|
||||
};
|
||||
|
||||
static SharedObjectHolder& getSharedObjectHolder() noexcept
|
||||
{
|
||||
static void* holder [(sizeof (SharedObjectHolder) + sizeof(void*) - 1) / sizeof(void*)] = { 0 };
|
||||
return *reinterpret_cast<SharedObjectHolder*> (holder);
|
||||
}
|
||||
|
||||
SharedObjectType* sharedObject;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedResourcePointer)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_SINGLETON_H_INCLUDED
|
||||
#define JUCE_SINGLETON_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Macro to declare member variables and methods for a singleton class.
|
||||
|
||||
To use this, add the line juce_DeclareSingleton (MyClass, doNotRecreateAfterDeletion)
|
||||
to the class's definition.
|
||||
|
||||
Then put a macro juce_ImplementSingleton (MyClass) along with the class's
|
||||
implementation code.
|
||||
|
||||
It's also a very good idea to also add the call clearSingletonInstance() in your class's
|
||||
destructor, in case it is deleted by other means than deleteInstance()
|
||||
|
||||
Clients can then call the static method MyClass::getInstance() to get a pointer
|
||||
to the singleton, or MyClass::getInstanceWithoutCreating() which will return 0 if
|
||||
no instance currently exists.
|
||||
|
||||
e.g. @code
|
||||
|
||||
class MySingleton
|
||||
{
|
||||
public:
|
||||
MySingleton()
|
||||
{
|
||||
}
|
||||
|
||||
~MySingleton()
|
||||
{
|
||||
// this ensures that no dangling pointers are left when the
|
||||
// singleton is deleted.
|
||||
clearSingletonInstance();
|
||||
}
|
||||
|
||||
juce_DeclareSingleton (MySingleton, false)
|
||||
};
|
||||
|
||||
juce_ImplementSingleton (MySingleton)
|
||||
|
||||
|
||||
// example of usage:
|
||||
MySingleton* m = MySingleton::getInstance(); // creates the singleton if there isn't already one.
|
||||
|
||||
...
|
||||
|
||||
MySingleton::deleteInstance(); // safely deletes the singleton (if it's been created).
|
||||
|
||||
@endcode
|
||||
|
||||
If doNotRecreateAfterDeletion = true, it won't allow the object to be created more
|
||||
than once during the process's lifetime - i.e. after you've created and deleted the
|
||||
object, getInstance() will refuse to create another one. This can be useful to stop
|
||||
objects being accidentally re-created during your app's shutdown code.
|
||||
|
||||
If you know that your object will only be created and deleted by a single thread, you
|
||||
can use the slightly more efficient juce_DeclareSingleton_SingleThreaded() macro instead
|
||||
of this one.
|
||||
|
||||
@see juce_ImplementSingleton, juce_DeclareSingleton_SingleThreaded
|
||||
*/
|
||||
#define juce_DeclareSingleton(classname, doNotRecreateAfterDeletion) \
|
||||
\
|
||||
static classname* _singletonInstance; \
|
||||
static juce::CriticalSection _singletonLock; \
|
||||
\
|
||||
static classname* JUCE_CALLTYPE getInstance() \
|
||||
{ \
|
||||
if (_singletonInstance == nullptr) \
|
||||
{\
|
||||
const juce::ScopedLock sl (_singletonLock); \
|
||||
\
|
||||
if (_singletonInstance == nullptr) \
|
||||
{ \
|
||||
static bool alreadyInside = false; \
|
||||
static bool createdOnceAlready = false; \
|
||||
\
|
||||
const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \
|
||||
jassert (! problem); \
|
||||
if (! problem) \
|
||||
{ \
|
||||
createdOnceAlready = true; \
|
||||
alreadyInside = true; \
|
||||
classname* newObject = new classname(); /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \
|
||||
alreadyInside = false; \
|
||||
\
|
||||
_singletonInstance = newObject; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static inline classname* JUCE_CALLTYPE getInstanceWithoutCreating() noexcept\
|
||||
{ \
|
||||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static void JUCE_CALLTYPE deleteInstance() \
|
||||
{ \
|
||||
const juce::ScopedLock sl (_singletonLock); \
|
||||
if (_singletonInstance != nullptr) \
|
||||
{ \
|
||||
classname* const old = _singletonInstance; \
|
||||
_singletonInstance = nullptr; \
|
||||
delete old; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void clearSingletonInstance() noexcept\
|
||||
{ \
|
||||
if (_singletonInstance == this) \
|
||||
_singletonInstance = nullptr; \
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** This is a counterpart to the juce_DeclareSingleton macro.
|
||||
|
||||
After adding the juce_DeclareSingleton to the class definition, this macro has
|
||||
to be used in the cpp file.
|
||||
*/
|
||||
#define juce_ImplementSingleton(classname) \
|
||||
\
|
||||
classname* classname::_singletonInstance = nullptr; \
|
||||
juce::CriticalSection classname::_singletonLock;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Macro to declare member variables and methods for a singleton class.
|
||||
|
||||
This is exactly the same as juce_DeclareSingleton, but doesn't use a critical
|
||||
section to make access to it thread-safe. If you know that your object will
|
||||
only ever be created or deleted by a single thread, then this is a
|
||||
more efficient version to use.
|
||||
|
||||
If doNotRecreateAfterDeletion = true, it won't allow the object to be created more
|
||||
than once during the process's lifetime - i.e. after you've created and deleted the
|
||||
object, getInstance() will refuse to create another one. This can be useful to stop
|
||||
objects being accidentally re-created during your app's shutdown code.
|
||||
|
||||
See the documentation for juce_DeclareSingleton for more information about
|
||||
how to use it, the only difference being that you have to use
|
||||
juce_ImplementSingleton_SingleThreaded instead of juce_ImplementSingleton.
|
||||
|
||||
@see juce_ImplementSingleton_SingleThreaded, juce_DeclareSingleton, juce_DeclareSingleton_SingleThreaded_Minimal
|
||||
*/
|
||||
#define juce_DeclareSingleton_SingleThreaded(classname, doNotRecreateAfterDeletion) \
|
||||
\
|
||||
static classname* _singletonInstance; \
|
||||
\
|
||||
static classname* getInstance() \
|
||||
{ \
|
||||
if (_singletonInstance == nullptr) \
|
||||
{ \
|
||||
static bool alreadyInside = false; \
|
||||
static bool createdOnceAlready = false; \
|
||||
\
|
||||
const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \
|
||||
jassert (! problem); \
|
||||
if (! problem) \
|
||||
{ \
|
||||
createdOnceAlready = true; \
|
||||
alreadyInside = true; \
|
||||
classname* newObject = new classname(); /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \
|
||||
alreadyInside = false; \
|
||||
\
|
||||
_singletonInstance = newObject; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static inline classname* getInstanceWithoutCreating() noexcept\
|
||||
{ \
|
||||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static void deleteInstance() \
|
||||
{ \
|
||||
if (_singletonInstance != nullptr) \
|
||||
{ \
|
||||
classname* const old = _singletonInstance; \
|
||||
_singletonInstance = nullptr; \
|
||||
delete old; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void clearSingletonInstance() noexcept\
|
||||
{ \
|
||||
if (_singletonInstance == this) \
|
||||
_singletonInstance = nullptr; \
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Macro to declare member variables and methods for a singleton class.
|
||||
|
||||
This is like juce_DeclareSingleton_SingleThreaded, but doesn't do any checking
|
||||
for recursion or repeated instantiation. It's intended for use as a lightweight
|
||||
version of a singleton, where you're using it in very straightforward
|
||||
circumstances and don't need the extra checking.
|
||||
|
||||
Juce use the normal juce_ImplementSingleton_SingleThreaded as the counterpart
|
||||
to this declaration, as you would with juce_DeclareSingleton_SingleThreaded.
|
||||
|
||||
See the documentation for juce_DeclareSingleton for more information about
|
||||
how to use it, the only difference being that you have to use
|
||||
juce_ImplementSingleton_SingleThreaded instead of juce_ImplementSingleton.
|
||||
|
||||
@see juce_ImplementSingleton_SingleThreaded, juce_DeclareSingleton
|
||||
*/
|
||||
#define juce_DeclareSingleton_SingleThreaded_Minimal(classname) \
|
||||
\
|
||||
static classname* _singletonInstance; \
|
||||
\
|
||||
static classname* getInstance() \
|
||||
{ \
|
||||
if (_singletonInstance == nullptr) \
|
||||
_singletonInstance = new classname(); \
|
||||
\
|
||||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static inline classname* getInstanceWithoutCreating() noexcept\
|
||||
{ \
|
||||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static void deleteInstance() \
|
||||
{ \
|
||||
if (_singletonInstance != nullptr) \
|
||||
{ \
|
||||
classname* const old = _singletonInstance; \
|
||||
_singletonInstance = nullptr; \
|
||||
delete old; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void clearSingletonInstance() noexcept\
|
||||
{ \
|
||||
if (_singletonInstance == this) \
|
||||
_singletonInstance = nullptr; \
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** This is a counterpart to the juce_DeclareSingleton_SingleThreaded macro.
|
||||
|
||||
After adding juce_DeclareSingleton_SingleThreaded or juce_DeclareSingleton_SingleThreaded_Minimal
|
||||
to the class definition, this macro has to be used somewhere in the cpp file.
|
||||
*/
|
||||
#define juce_ImplementSingleton_SingleThreaded(classname) \
|
||||
\
|
||||
classname* classname::_singletonInstance = nullptr;
|
||||
|
||||
|
||||
|
||||
#endif // JUCE_SINGLETON_H_INCLUDED
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the juce_core module of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with
|
||||
or without fee is hereby granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
|
||||
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
|
||||
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
|
||||
using any other modules, be sure to check that you also comply with their license.
|
||||
|
||||
For more details, visit www.juce.com
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_WEAKREFERENCE_H_INCLUDED
|
||||
#define JUCE_WEAKREFERENCE_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
This class acts as a pointer which will automatically become null if the object
|
||||
to which it points is deleted.
|
||||
|
||||
To accomplish this, the source object needs to cooperate by performing a couple of simple tasks.
|
||||
It must embed a WeakReference::Master object, which stores a shared pointer object, and must clear
|
||||
this master pointer in its destructor.
|
||||
|
||||
E.g.
|
||||
@code
|
||||
class MyObject
|
||||
{
|
||||
public:
|
||||
MyObject()
|
||||
{
|
||||
// If you're planning on using your WeakReferences in a multi-threaded situation, you may choose
|
||||
// to create a WeakReference to the object here in the constructor, which will pre-initialise the
|
||||
// embedded object, avoiding an (extremely unlikely) race condition that could occur if multiple
|
||||
// threads overlap while creating the first WeakReference to it.
|
||||
}
|
||||
|
||||
~MyObject()
|
||||
{
|
||||
// This will zero all the references - you need to call this in your destructor.
|
||||
masterReference.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
// You need to embed a variable of this type, with the name "masterReference" inside your object. If the
|
||||
// variable is not public, you should make your class a friend of WeakReference<MyObject> so that the
|
||||
// WeakReference class can access it.
|
||||
WeakReference<MyObject>::Master masterReference;
|
||||
friend class WeakReference<MyObject>;
|
||||
};
|
||||
|
||||
// Here's an example of using a pointer..
|
||||
|
||||
MyObject* n = new MyObject();
|
||||
WeakReference<MyObject> myObjectRef = n;
|
||||
|
||||
MyObject* pointer1 = myObjectRef; // returns a valid pointer to 'n'
|
||||
delete n;
|
||||
MyObject* pointer2 = myObjectRef; // returns a null pointer
|
||||
@endcode
|
||||
|
||||
@see WeakReference::Master
|
||||
*/
|
||||
template <class ObjectType, class ReferenceCountingType = ReferenceCountedObject>
|
||||
class WeakReference
|
||||
{
|
||||
public:
|
||||
/** Creates a null SafePointer. */
|
||||
inline WeakReference() noexcept {}
|
||||
|
||||
/** Creates a WeakReference that points at the given object. */
|
||||
WeakReference (ObjectType* const object) : holder (getRef (object)) {}
|
||||
|
||||
/** Creates a copy of another WeakReference. */
|
||||
WeakReference (const WeakReference& other) noexcept : holder (other.holder) {}
|
||||
|
||||
/** Copies another pointer to this one. */
|
||||
WeakReference& operator= (const WeakReference& other) { holder = other.holder; return *this; }
|
||||
|
||||
/** Copies another pointer to this one. */
|
||||
WeakReference& operator= (ObjectType* const newObject) { holder = getRef (newObject); return *this; }
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
WeakReference (WeakReference&& other) noexcept : holder (static_cast <SharedRef&&> (other.holder)) {}
|
||||
WeakReference& operator= (WeakReference&& other) noexcept { holder = static_cast <SharedRef&&> (other.holder); return *this; }
|
||||
#endif
|
||||
|
||||
/** Returns the object that this pointer refers to, or null if the object no longer exists. */
|
||||
ObjectType* get() const noexcept { return holder != nullptr ? holder->get() : nullptr; }
|
||||
|
||||
/** Returns the object that this pointer refers to, or null if the object no longer exists. */
|
||||
operator ObjectType*() const noexcept { return get(); }
|
||||
|
||||
/** Returns the object that this pointer refers to, or null if the object no longer exists. */
|
||||
ObjectType* operator->() noexcept { return get(); }
|
||||
|
||||
/** Returns the object that this pointer refers to, or null if the object no longer exists. */
|
||||
const ObjectType* operator->() const noexcept { return get(); }
|
||||
|
||||
/** This returns true if this reference has been pointing at an object, but that object has
|
||||
since been deleted.
|
||||
|
||||
If this reference was only ever pointing at a null pointer, this will return false. Using
|
||||
operator=() to make this refer to a different object will reset this flag to match the status
|
||||
of the reference from which you're copying.
|
||||
*/
|
||||
bool wasObjectDeleted() const noexcept { return holder != nullptr && holder->get() == nullptr; }
|
||||
|
||||
bool operator== (ObjectType* const object) const noexcept { return get() == object; }
|
||||
bool operator!= (ObjectType* const object) const noexcept { return get() != object; }
|
||||
|
||||
//==============================================================================
|
||||
/** This class is used internally by the WeakReference class - don't use it directly
|
||||
in your code!
|
||||
@see WeakReference
|
||||
*/
|
||||
class SharedPointer : public ReferenceCountingType
|
||||
{
|
||||
public:
|
||||
explicit SharedPointer (ObjectType* const obj) noexcept : owner (obj) {}
|
||||
|
||||
inline ObjectType* get() const noexcept { return owner; }
|
||||
void clearPointer() noexcept { owner = nullptr; }
|
||||
|
||||
private:
|
||||
ObjectType* volatile owner;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (SharedPointer)
|
||||
};
|
||||
|
||||
typedef ReferenceCountedObjectPtr<SharedPointer> SharedRef;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
This class is embedded inside an object to which you want to attach WeakReference pointers.
|
||||
See the WeakReference class notes for an example of how to use this class.
|
||||
@see WeakReference
|
||||
*/
|
||||
class Master
|
||||
{
|
||||
public:
|
||||
Master() noexcept {}
|
||||
|
||||
~Master() noexcept
|
||||
{
|
||||
// You must remember to call clear() in your source object's destructor! See the notes
|
||||
// for the WeakReference class for an example of how to do this.
|
||||
jassert (sharedPointer == nullptr || sharedPointer->get() == nullptr);
|
||||
}
|
||||
|
||||
/** The first call to this method will create an internal object that is shared by all weak
|
||||
references to the object.
|
||||
*/
|
||||
SharedPointer* getSharedPointer (ObjectType* const object)
|
||||
{
|
||||
if (sharedPointer == nullptr)
|
||||
{
|
||||
sharedPointer = new SharedPointer (object);
|
||||
}
|
||||
else
|
||||
{
|
||||
// You're trying to create a weak reference to an object that has already been deleted!!
|
||||
jassert (sharedPointer->get() != nullptr);
|
||||
}
|
||||
|
||||
return sharedPointer;
|
||||
}
|
||||
|
||||
/** The object that owns this master pointer should call this before it gets destroyed,
|
||||
to zero all the references to this object that may be out there. See the WeakReference
|
||||
class notes for an example of how to do this.
|
||||
*/
|
||||
void clear() noexcept
|
||||
{
|
||||
if (sharedPointer != nullptr)
|
||||
sharedPointer->clearPointer();
|
||||
}
|
||||
|
||||
private:
|
||||
SharedRef sharedPointer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (Master)
|
||||
};
|
||||
|
||||
private:
|
||||
SharedRef holder;
|
||||
|
||||
static inline SharedPointer* getRef (ObjectType* const o)
|
||||
{
|
||||
return (o != nullptr) ? o->masterReference.getSharedPointer (o) : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_WEAKREFERENCE_H_INCLUDED
|
||||
Reference in New Issue
Block a user