Loading...
Searching...
No Matches
juce_HeapBlock.h
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. 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.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
#if ! (DOXYGEN || JUCE_EXCEPTIONS_DISABLED)
namespace HeapBlockHelper
{
template <bool shouldThrow>
struct ThrowOnFail { static void checkPointer (void*) {} };
template <>
struct ThrowOnFail<true> { static void checkPointer (void* data) { if (data == nullptr) throw std::bad_alloc(); } };
}
#endif
//==============================================================================
template <class ElementType, bool throwOnFailure = false>
class HeapBlock
{
private:
template <class OtherElementType>
using AllowConversion = std::enable_if_t<std::is_base_of_v<std::remove_pointer_t<ElementType>,
std::remove_pointer_t<OtherElementType>>>;
public:
//==============================================================================
HeapBlock() = default;
template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>
explicit HeapBlock (SizeType numElements)
: data (mallocWrapper (static_cast<size_t> (numElements) * sizeof (ElementType)))
{
}
template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>
HeapBlock (SizeType numElements, bool initialiseToZero)
: data (initialiseToZero ? callocWrapper (static_cast<size_t> (numElements), sizeof (ElementType))
: mallocWrapper (static_cast<size_t> (numElements) * sizeof (ElementType)))
{
}
~HeapBlock()
{
std::free (data);
}
HeapBlock (HeapBlock&& other) noexcept
: data (other.data)
{
other.data = nullptr;
}
HeapBlock& operator= (HeapBlock&& other) noexcept
{
std::swap (data, other.data);
return *this;
}
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
HeapBlock (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept
: data (reinterpret_cast<ElementType*> (other.data))
{
other.data = nullptr;
}
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
HeapBlock& operator= (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept
{
free();
data = reinterpret_cast<ElementType*> (other.data);
other.data = nullptr;
return *this;
}
//==============================================================================
inline operator ElementType*() const noexcept { return data; }
inline ElementType* get() const noexcept { return data; }
inline ElementType* getData() const noexcept { return data; }
inline operator void*() const noexcept { return static_cast<void*> (data); }
inline operator const void*() const noexcept { return static_cast<const void*> (data); }
inline ElementType* operator->() const noexcept { return data; }
template <typename IndexType>
ElementType& operator[] (IndexType index) const noexcept { return data [index]; }
template <typename IndexType>
ElementType* operator+ (IndexType index) const noexcept { return data + index; }
//==============================================================================
inline bool operator== (const ElementType* otherPointer) const noexcept { return otherPointer == data; }
inline bool operator!= (const ElementType* otherPointer) const noexcept { return otherPointer != data; }
//==============================================================================
template <typename SizeType>
void malloc (SizeType newNumElements, size_t elementSize = sizeof (ElementType))
{
std::free (data);
data = mallocWrapper (static_cast<size_t> (newNumElements) * elementSize);
}
template <typename SizeType>
void calloc (SizeType newNumElements, const size_t elementSize = sizeof (ElementType))
{
std::free (data);
data = callocWrapper (static_cast<size_t> (newNumElements), elementSize);
}
template <typename SizeType>
void allocate (SizeType newNumElements, bool initialiseToZero)
{
std::free (data);
data = initialiseToZero ? callocWrapper (static_cast<size_t> (newNumElements), sizeof (ElementType))
: mallocWrapper (static_cast<size_t> (newNumElements) * sizeof (ElementType));
}
template <typename SizeType>
void realloc (SizeType newNumElements, size_t elementSize = sizeof (ElementType))
{
data = reallocWrapper (data, static_cast<size_t> (newNumElements) * elementSize);
}
void free() noexcept
{
std::free (data);
data = nullptr;
}
template <bool otherBlockThrows>
void swapWith (HeapBlock<ElementType, otherBlockThrows>& other) noexcept
{
std::swap (data, other.data);
}
template <typename SizeType>
void clear (SizeType numElements) noexcept
{
zeromem (data, sizeof (ElementType) * static_cast<size_t> (numElements));
}
using Type = ElementType;
private:
//==============================================================================
// Calls to malloc, calloc and realloc with zero size have implementation-defined
// behaviour where either nullptr or a non-null pointer is returned.
template <typename Functor>
static ElementType* wrapper (size_t size, Functor&& f)
{
if (size == 0)
return nullptr;
auto* memory = static_cast<ElementType*> (f());
#if JUCE_EXCEPTIONS_DISABLED
jassert (memory != nullptr); // without exceptions, you'll need to find a better way to handle this failure case.
#else
HeapBlockHelper::ThrowOnFail<throwOnFailure>::checkPointer (memory);
#endif
return memory;
}
static ElementType* mallocWrapper (size_t size)
{
return wrapper (size, [size] { return std::malloc (size); });
}
static ElementType* callocWrapper (size_t num, size_t size)
{
return wrapper (num * size, [num, size] { return std::calloc (num, size); });
}
static ElementType* reallocWrapper (void* ptr, size_t newSize)
{
return wrapper (newSize, [ptr, newSize] { return std::realloc (ptr, newSize); });
}
template <class OtherElementType, bool otherThrowOnFailure>
friend class HeapBlock;
//==============================================================================
ElementType* data = nullptr;
#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
};
} // namespace juce
juce::HeapBlock::~HeapBlock
~HeapBlock()
Definition juce_HeapBlock.h:131
juce::HeapBlock::HeapBlock
HeapBlock(SizeType numElements)
Definition juce_HeapBlock.h:111
juce::HeapBlock::HeapBlock
HeapBlock(HeapBlock< OtherElementType, otherThrowOnFailure > &&other) noexcept
Definition juce_HeapBlock.h:155
juce::HeapBlock::operator=
HeapBlock & operator=(HeapBlock &&other) noexcept
Definition juce_HeapBlock.h:144
juce::HeapBlock::Type
ElementType Type
Definition juce_HeapBlock.h:317
juce::HeapBlock::clear
void clear(SizeType numElements) noexcept
Definition juce_HeapBlock.h:311
juce::HeapBlock::swapWith
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
Definition juce_HeapBlock.h:301
juce::HeapBlock::operator!=
bool operator!=(const ElementType *otherPointer) const noexcept
Definition juce_HeapBlock.h:233
juce::HeapBlock::operator+
ElementType * operator+(IndexType index) const noexcept
Definition juce_HeapBlock.h:222
juce::HeapBlock::malloc
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Definition juce_HeapBlock.h:249
juce::HeapBlock::HeapBlock
HeapBlock(HeapBlock &&other) noexcept
Definition juce_HeapBlock.h:137
juce::HeapBlock::get
ElementType * get() const noexcept
Definition juce_HeapBlock.h:185
juce::HeapBlock::getData
ElementType * getData() const noexcept
Definition juce_HeapBlock.h:191
juce::HeapBlock::operator[]
ElementType & operator[](IndexType index) const noexcept
Definition juce_HeapBlock.h:216
juce::HeapBlock::HeapBlock
HeapBlock()=default
juce::HeapBlock::allocate
void allocate(SizeType newNumElements, bool initialiseToZero)
Definition juce_HeapBlock.h:270
juce::HeapBlock::HeapBlock
HeapBlock(SizeType numElements, bool initialiseToZero)
Definition juce_HeapBlock.h:122
juce::HeapBlock::operator==
bool operator==(const ElementType *otherPointer) const noexcept
Definition juce_HeapBlock.h:228
juce::HeapBlock::realloc
void realloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Definition juce_HeapBlock.h:283
juce::HeapBlock::free
void free() noexcept
Definition juce_HeapBlock.h:291
juce::HeapBlock::operator->
ElementType * operator->() const noexcept
Definition juce_HeapBlock.h:209
juce::HeapBlock::calloc
void calloc(SizeType newNumElements, const size_t elementSize=sizeof(ElementType))
Definition juce_HeapBlock.h:259