Loading...
Searching...
No Matches
juce_ReferenceCountedArray.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
{
//==============================================================================
template <class ObjectClass, class TypeOfCriticalSectionToUse = DummyCriticalSection>
class ReferenceCountedArray
{
public:
using ObjectClassPtr = ReferenceCountedObjectPtr<ObjectClass>;
//==============================================================================
ReferenceCountedArray() = default;
ReferenceCountedArray (const ReferenceCountedArray& other) noexcept
{
const ScopedLockType lock (other.getLock());
values.addArray (other.begin(), other.size());
for (auto* o : *this)
if (o != nullptr)
o->incReferenceCount();
}
ReferenceCountedArray (ReferenceCountedArray&& other) noexcept
: values (std::move (other.values))
{
}
template <class OtherObjectClass, class OtherCriticalSection>
ReferenceCountedArray (const ReferenceCountedArray<OtherObjectClass, OtherCriticalSection>& other) noexcept
{
const typename ReferenceCountedArray<OtherObjectClass, OtherCriticalSection>::ScopedLockType lock (other.getLock());
values.addArray (other.begin(), other.size());
for (auto* o : *this)
if (o != nullptr)
o->incReferenceCount();
}
ReferenceCountedArray& operator= (const ReferenceCountedArray& other) noexcept
{
releaseAllObjects();
auto otherCopy = other;
swapWith (otherCopy);
return *this;
}
template <class OtherObjectClass>
ReferenceCountedArray& operator= (const ReferenceCountedArray<OtherObjectClass, TypeOfCriticalSectionToUse>& other) noexcept
{
auto otherCopy = other;
swapWith (otherCopy);
return *this;
}
ReferenceCountedArray& operator= (ReferenceCountedArray&& other) noexcept
{
releaseAllObjects();
values = std::move (other.values);
return *this;
}
~ReferenceCountedArray()
{
releaseAllObjects();
}
//==============================================================================
void clear()
{
const ScopedLockType lock (getLock());
clearQuick();
values.setAllocatedSize (0);
}
void clearQuick()
{
const ScopedLockType lock (getLock());
releaseAllObjects();
}
inline int size() const noexcept
{
return values.size();
}
inline bool isEmpty() const noexcept
{
return size() == 0;
}
inline ObjectClassPtr operator[] (int index) const noexcept
{
return ObjectClassPtr (getObjectPointer (index));
}
inline ObjectClassPtr getUnchecked (int index) const noexcept
{
return ObjectClassPtr (getObjectPointerUnchecked (index));
}
inline ObjectClass* getObjectPointer (int index) const noexcept
{
const ScopedLockType lock (getLock());
return values.getValueWithDefault (index);
}
inline ObjectClass* getObjectPointerUnchecked (int index) const noexcept
{
const ScopedLockType lock (getLock());
return values[index];
}
inline ObjectClassPtr getFirst() const noexcept
{
const ScopedLockType lock (getLock());
return values.getFirst();
}
inline ObjectClassPtr getLast() const noexcept
{
const ScopedLockType lock (getLock());
return values.getLast();
}
inline ObjectClass** getRawDataPointer() const noexcept
{
return values.begin();
}
//==============================================================================
inline ObjectClass** begin() noexcept
{
return values.begin();
}
inline ObjectClass* const* begin() const noexcept
{
return values.begin();
}
inline ObjectClass** end() noexcept
{
return values.end();
}
inline ObjectClass* const* end() const noexcept
{
return values.end();
}
inline ObjectClass** data() noexcept
{
return begin();
}
inline ObjectClass* const* data() const noexcept
{
return begin();
}
//==============================================================================
int indexOf (const ObjectClass* objectToLookFor) const noexcept
{
const ScopedLockType lock (getLock());
auto* e = values.begin();
auto* endPointer = values.end();
while (e != endPointer)
{
if (objectToLookFor == *e)
return static_cast<int> (e - values.begin());
++e;
}
return -1;
}
int indexOf (const ObjectClassPtr& objectToLookFor) const noexcept { return indexOf (objectToLookFor.get()); }
bool contains (const ObjectClass* objectToLookFor) const noexcept
{
const ScopedLockType lock (getLock());
auto* e = values.begin();
auto* endPointer = values.end();
while (e != endPointer)
{
if (objectToLookFor == *e)
return true;
++e;
}
return false;
}
bool contains (const ObjectClassPtr& objectToLookFor) const noexcept { return contains (objectToLookFor.get()); }
ObjectClass* add (ObjectClass* newObject)
{
const ScopedLockType lock (getLock());
values.add (newObject);
if (newObject != nullptr)
newObject->incReferenceCount();
return newObject;
}
ObjectClass* add (const ObjectClassPtr& newObject) { return add (newObject.get()); }
ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
{
values.insert (indexToInsertAt, newObject, 1);
if (newObject != nullptr)
newObject->incReferenceCount();
return newObject;
}
ObjectClass* insert (int indexToInsertAt, const ObjectClassPtr& newObject) { return insert (indexToInsertAt, newObject.get()); }
bool addIfNotAlreadyThere (ObjectClass* newObject)
{
const ScopedLockType lock (getLock());
if (contains (newObject))
return false;
add (newObject);
return true;
}
bool addIfNotAlreadyThere (const ObjectClassPtr& newObject) { return addIfNotAlreadyThere (newObject.get()); }
void set (int indexToChange, ObjectClass* newObject)
{
if (indexToChange >= 0)
{
const ScopedLockType lock (getLock());
if (newObject != nullptr)
newObject->incReferenceCount();
if (indexToChange < values.size())
{
auto* e = values[indexToChange];
values[indexToChange] = newObject;
releaseObject (e);
}
else
{
values.add (newObject);
}
}
}
void set (int indexToChange, const ObjectClassPtr& newObject) { set (indexToChange, newObject.get()); }
void addArray (const ReferenceCountedArray& arrayToAddFrom,
int startIndex = 0,
int numElementsToAdd = -1) noexcept
{
const ScopedLockType lock1 (arrayToAddFrom.getLock());
{
const ScopedLockType lock2 (getLock());
auto numElementsAdded = values.addArray (arrayToAddFrom.values, startIndex, numElementsToAdd);
auto** e = values.end();
for (int i = 0; i < numElementsAdded; ++i)
(*(--e))->incReferenceCount();
}
}
template <class ElementComparator>
int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
{
const ScopedLockType lock (getLock());
auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
insert (index, newObject);
return index;
}
template <class ElementComparator>
void addOrReplaceSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
{
const ScopedLockType lock (getLock());
auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
if (index > 0 && comparator.compareElements (newObject, values[index - 1]) == 0)
set (index - 1, newObject); // replace an existing object that matches
else
insert (index, newObject); // no match, so insert the new one
}
template <class ElementComparator>
int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept;
//==============================================================================
void remove (int indexToRemove)
{
const ScopedLockType lock (getLock());
if (isPositiveAndBelow (indexToRemove, values.size()))
{
auto* e = *(values.begin() + indexToRemove);
values.removeElements (indexToRemove, 1);
releaseObject (e);
if ((values.size() << 1) < values.capacity())
minimiseStorageOverheads();
}
}
ObjectClassPtr removeAndReturn (int indexToRemove)
{
ObjectClassPtr removedItem;
const ScopedLockType lock (getLock());
if (isPositiveAndBelow (indexToRemove, values.size()))
{
auto* e = *(values.begin() + indexToRemove);
removedItem = e;
values.removeElements (indexToRemove, 1);
releaseObject (e);
if ((values.size() << 1) < values.capacity())
minimiseStorageOverheads();
}
return removedItem;
}
void removeObject (ObjectClass* objectToRemove)
{
const ScopedLockType lock (getLock());
remove (indexOf (objectToRemove));
}
void removeObject (const ObjectClassPtr& objectToRemove) { removeObject (objectToRemove.get()); }
void removeRange (int startIndex,
int numberToRemove)
{
const ScopedLockType lock (getLock());
startIndex = jlimit (0, values.size(), startIndex);
auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
numberToRemove = endIndex - startIndex;
if (numberToRemove > 0)
{
Array<ObjectClass*> objectsToRemove;
objectsToRemove.addArray (values.begin() + startIndex, numberToRemove);
values.removeElements (startIndex, numberToRemove);
for (auto& o : objectsToRemove)
releaseObject (o);
if ((values.size() << 1) < values.capacity())
minimiseStorageOverheads();
}
}
void removeLast (int howManyToRemove = 1)
{
const ScopedLockType lock (getLock());
if (howManyToRemove > values.size())
howManyToRemove = values.size();
while (--howManyToRemove >= 0)
remove (values.size() - 1);
}
void swap (int index1, int index2) noexcept
{
const ScopedLockType lock (getLock());
if (isPositiveAndBelow (index1, values.size())
&& isPositiveAndBelow (index2, values.size()))
{
std::swap (values[index1], values[index2]);
}
}
void move (int currentIndex, int newIndex) noexcept
{
if (currentIndex != newIndex)
{
const ScopedLockType lock (getLock());
values.move (currentIndex, newIndex);
}
}
//==============================================================================
template <class OtherArrayType>
void swapWith (OtherArrayType& otherArray) noexcept
{
const ScopedLockType lock1 (getLock());
const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
values.swapWith (otherArray.values);
}
//==============================================================================
bool operator== (const ReferenceCountedArray& other) const noexcept
{
const ScopedLockType lock2 (other.getLock());
const ScopedLockType lock1 (getLock());
return values == other.values;
}
bool operator!= (const ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& other) const noexcept
{
return ! operator== (other);
}
//==============================================================================
template <class ElementComparator>
void sort (ElementComparator& comparator, bool retainOrderOfEquivalentItems = false) noexcept;
//==============================================================================
void minimiseStorageOverheads() noexcept
{
const ScopedLockType lock (getLock());
values.shrinkToNoMoreThan (values.size());
}
void ensureStorageAllocated (const int minNumElements)
{
const ScopedLockType lock (getLock());
values.ensureAllocatedSize (minNumElements);
}
//==============================================================================
inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
//==============================================================================
#ifndef DOXYGEN
[[deprecated ("This method has been replaced by a more flexible templated version and renamed "
"to swapWith to be more consistent with the names used in other classes.")]]
void swapWithArray (ReferenceCountedArray& other) noexcept { swapWith (other); }
#endif
private:
//==============================================================================
ArrayBase<ObjectClass*, TypeOfCriticalSectionToUse> values;
void releaseAllObjects()
{
auto i = values.size();
while (--i >= 0)
{
auto* e = values[i];
values.removeElements (i, 1);
releaseObject (e);
}
}
static void releaseObject (ObjectClass* o)
{
if (o != nullptr && o->decReferenceCountWithoutDeleting())
ContainerDeletePolicy<ObjectClass>::destroy (o);
}
};
//==============================================================================
template <class ObjectClass, class TypeOfCriticalSectionToUse>
template <class ElementComparator>
int ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>::indexOfSorted (
[[maybe_unused]] ElementComparator& comparator,
const ObjectClass* objectToLookFor) const noexcept
{
const ScopedLockType lock (getLock());
int s = 0, e = values.size();
while (s < e)
{
if (comparator.compareElements (objectToLookFor, values[s]) == 0)
return s;
auto halfway = (s + e) / 2;
if (halfway == s)
break;
if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
s = halfway;
else
e = halfway;
}
return -1;
}
template <class ObjectClass, class TypeOfCriticalSectionToUse>
template <class ElementComparator>
void ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>::sort (
[[maybe_unused]] ElementComparator& comparator,
bool retainOrderOfEquivalentItems) noexcept
{
const ScopedLockType lock (getLock());
sortArray (comparator, values.begin(), 0, values.size() - 1, retainOrderOfEquivalentItems);
}
} // namespace juce
juce::ArrayBase
Definition juce_ArrayBase.h:41
juce::Array
Definition juce_Array.h:56
juce::Array::addArray
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition juce_Array.h:583
juce::ReferenceCountedArray::ReferenceCountedArray
ReferenceCountedArray(ReferenceCountedArray &&other) noexcept
Definition juce_ReferenceCountedArray.h:73
juce::ReferenceCountedArray::add
ObjectClass * add(const ObjectClassPtr &newObject)
Definition juce_ReferenceCountedArray.h:372
juce::ReferenceCountedArray::isEmpty
bool isEmpty() const noexcept
Definition juce_ReferenceCountedArray.h:156
juce::ReferenceCountedArray::indexOf
int indexOf(const ObjectClass *objectToLookFor) const noexcept
Definition juce_ReferenceCountedArray.h:294
juce::ReferenceCountedArray::ReferenceCountedArray
ReferenceCountedArray(const ReferenceCountedArray &other) noexcept
Definition juce_ReferenceCountedArray.h:62
juce::ReferenceCountedArray::size
int size() const noexcept
Definition juce_ReferenceCountedArray.h:150
juce::ReferenceCountedArray::removeLast
void removeLast(int howManyToRemove=1)
Definition juce_ReferenceCountedArray.h:695
juce::ReferenceCountedArray::end
ObjectClass *const * end() const noexcept
Definition juce_ReferenceCountedArray.h:267
juce::ReferenceCountedArray::minimiseStorageOverheads
void minimiseStorageOverheads() noexcept
Definition juce_ReferenceCountedArray.h:816
juce::ReferenceCountedArray::set
void set(int indexToChange, ObjectClass *newObject)
Definition juce_ReferenceCountedArray.h:453
juce::ReferenceCountedArray::begin
ObjectClass *const * begin() const noexcept
Definition juce_ReferenceCountedArray.h:251
juce::ReferenceCountedArray::insert
ObjectClass * insert(int indexToInsertAt, const ObjectClassPtr &newObject)
Definition juce_ReferenceCountedArray.h:410
juce::ReferenceCountedArray::ReferenceCountedArray
ReferenceCountedArray()=default
juce::ReferenceCountedArray::operator!=
bool operator!=(const ReferenceCountedArray< ObjectClass, TypeOfCriticalSectionToUse > &other) const noexcept
Definition juce_ReferenceCountedArray.h:774
juce::ReferenceCountedArray::indexOfSorted
int indexOfSorted(ElementComparator &comparator, const ObjectClass *objectToLookFor) const noexcept
Definition juce_ReferenceCountedArray.h:877
juce::ReferenceCountedArray::ScopedLockType
typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
Definition juce_ReferenceCountedArray.h:842
juce::ReferenceCountedArray::addIfNotAlreadyThere
bool addIfNotAlreadyThere(ObjectClass *newObject)
Definition juce_ReferenceCountedArray.h:420
juce::ReferenceCountedArray::operator[]
ObjectClassPtr operator[](int index) const noexcept
Definition juce_ReferenceCountedArray.h:169
juce::ReferenceCountedArray::remove
void remove(int indexToRemove)
Definition juce_ReferenceCountedArray.h:582
juce::ReferenceCountedArray::sort
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) noexcept
Definition juce_ReferenceCountedArray.h:905
juce::ReferenceCountedArray::ReferenceCountedArray
ReferenceCountedArray(const ReferenceCountedArray< OtherObjectClass, OtherCriticalSection > &other) noexcept
Definition juce_ReferenceCountedArray.h:80
juce::ReferenceCountedArray::operator==
bool operator==(const ReferenceCountedArray &other) const noexcept
Definition juce_ReferenceCountedArray.h:763
juce::ReferenceCountedArray::removeObject
void removeObject(ObjectClass *objectToRemove)
Definition juce_ReferenceCountedArray.h:633
juce::ReferenceCountedArray::getObjectPointer
ObjectClass * getObjectPointer(int index) const noexcept
Definition juce_ReferenceCountedArray.h:193
juce::ReferenceCountedArray::swap
void swap(int index1, int index2) noexcept
Definition juce_ReferenceCountedArray.h:711
juce::ReferenceCountedArray::getFirst
ObjectClassPtr getFirst() const noexcept
Definition juce_ReferenceCountedArray.h:213
juce::ReferenceCountedArray::ensureStorageAllocated
void ensureStorageAllocated(const int minNumElements)
Definition juce_ReferenceCountedArray.h:828
juce::ReferenceCountedArray::~ReferenceCountedArray
~ReferenceCountedArray()
Definition juce_ReferenceCountedArray.h:123
juce::ReferenceCountedArray::clearQuick
void clearQuick()
Definition juce_ReferenceCountedArray.h:143
juce::ReferenceCountedArray::set
void set(int indexToChange, const ObjectClassPtr &newObject)
Definition juce_ReferenceCountedArray.h:487
juce::ReferenceCountedArray::data
ObjectClass *const * data() const noexcept
Definition juce_ReferenceCountedArray.h:283
juce::ReferenceCountedArray::getLock
const TypeOfCriticalSectionToUse & getLock() const noexcept
Definition juce_ReferenceCountedArray.h:839
juce::ReferenceCountedArray::getUnchecked
ObjectClassPtr getUnchecked(int index) const noexcept
Definition juce_ReferenceCountedArray.h:180
juce::ReferenceCountedArray::begin
ObjectClass ** begin() noexcept
Definition juce_ReferenceCountedArray.h:243
juce::ReferenceCountedArray::addOrReplaceSorted
void addOrReplaceSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Definition juce_ReferenceCountedArray.h:542
juce::ReferenceCountedArray::contains
bool contains(const ObjectClass *objectToLookFor) const noexcept
Definition juce_ReferenceCountedArray.h:323
juce::ReferenceCountedArray::removeRange
void removeRange(int startIndex, int numberToRemove)
Definition juce_ReferenceCountedArray.h:664
juce::ReferenceCountedArray::getObjectPointerUnchecked
ObjectClass * getObjectPointerUnchecked(int index) const noexcept
Definition juce_ReferenceCountedArray.h:202
juce::ReferenceCountedArray::move
void move(int currentIndex, int newIndex) noexcept
Definition juce_ReferenceCountedArray.h:735
juce::ReferenceCountedArray::removeAndReturn
ObjectClassPtr removeAndReturn(int indexToRemove)
Definition juce_ReferenceCountedArray.h:606
juce::ReferenceCountedArray::operator=
ReferenceCountedArray & operator=(const ReferenceCountedArray &other) noexcept
Definition juce_ReferenceCountedArray.h:93
juce::ReferenceCountedArray::end
ObjectClass ** end() noexcept
Definition juce_ReferenceCountedArray.h:259
juce::ReferenceCountedArray::clear
void clear()
Definition juce_ReferenceCountedArray.h:132
juce::ReferenceCountedArray::getRawDataPointer
ObjectClass ** getRawDataPointer() const noexcept
Definition juce_ReferenceCountedArray.h:234
juce::ReferenceCountedArray::contains
bool contains(const ObjectClassPtr &objectToLookFor) const noexcept
Definition juce_ReferenceCountedArray.h:345
juce::ReferenceCountedArray::data
ObjectClass ** data() noexcept
Definition juce_ReferenceCountedArray.h:275
juce::ReferenceCountedArray::swapWith
void swapWith(OtherArrayType &otherArray) noexcept
Definition juce_ReferenceCountedArray.h:751
juce::ReferenceCountedArray::addIfNotAlreadyThere
bool addIfNotAlreadyThere(const ObjectClassPtr &newObject)
Definition juce_ReferenceCountedArray.h:439
juce::ReferenceCountedArray::addSorted
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Definition juce_ReferenceCountedArray.h:528
juce::ReferenceCountedArray::indexOf
int indexOf(const ObjectClassPtr &objectToLookFor) const noexcept
Definition juce_ReferenceCountedArray.h:316
juce::ReferenceCountedArray::getLast
ObjectClassPtr getLast() const noexcept
Definition juce_ReferenceCountedArray.h:224
juce::ReferenceCountedArray::addArray
void addArray(const ReferenceCountedArray &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1) noexcept
Definition juce_ReferenceCountedArray.h:498
juce::ReferenceCountedArray::insert
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
Definition juce_ReferenceCountedArray.h:387
juce::ReferenceCountedArray::add
ObjectClass * add(ObjectClass *newObject)
Definition juce_ReferenceCountedArray.h:354
juce::ReferenceCountedArray::removeObject
void removeObject(const ObjectClassPtr &objectToRemove)
Definition juce_ReferenceCountedArray.h:647
juce::ReferenceCountedObjectPtr
Definition juce_ReferenceCountedObject.h:247
juce::ReferenceCountedObjectPtr::get
ReferencedType * get() const noexcept
Definition juce_ReferenceCountedObject.h:381