JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_ReferenceCountedArray.h
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26//==============================================================================
49template <class ObjectClass, class TypeOfCriticalSectionToUse = DummyCriticalSection>
51{
52public:
54
55 //==============================================================================
60
63 {
64 const ScopedLockType lock (other.getLock());
65 values.addArray (other.begin(), other.size());
66
67 for (auto* o : *this)
68 if (o != nullptr)
69 o->incReferenceCount();
70 }
71
74 : values (std::move (other.values))
75 {
76 }
77
79 template <class OtherObjectClass, class OtherCriticalSection>
81 {
83 values.addArray (other.begin(), other.size());
84
85 for (auto* o : *this)
86 if (o != nullptr)
87 o->incReferenceCount();
88 }
89
94 {
95 releaseAllObjects();
96 auto otherCopy = other;
98 return *this;
99 }
100
104 template <class OtherObjectClass>
111
114 {
115 releaseAllObjects();
116 values = std::move (other.values);
117 return *this;
118 }
119
124 {
125 releaseAllObjects();
126 }
127
128 //==============================================================================
132 void clear()
133 {
134 const ScopedLockType lock (getLock());
135 clearQuick();
136 values.setAllocatedSize (0);
137 }
138
144 {
145 const ScopedLockType lock (getLock());
146 releaseAllObjects();
147 }
148
150 inline int size() const noexcept
151 {
152 return values.size();
153 }
154
156 inline bool isEmpty() const noexcept
157 {
158 return size() == 0;
159 }
160
169 inline ObjectClassPtr operator[] (int index) const noexcept
170 {
171 return ObjectClassPtr (getObjectPointer (index));
172 }
173
180 inline ObjectClassPtr getUnchecked (int index) const noexcept
181 {
183 }
184
193 inline ObjectClass* getObjectPointer (int index) const noexcept
194 {
195 const ScopedLockType lock (getLock());
196 return values.getValueWithDefault (index);
197 }
198
202 inline ObjectClass* getObjectPointerUnchecked (int index) const noexcept
203 {
204 const ScopedLockType lock (getLock());
205 return values[index];
206 }
207
213 inline ObjectClassPtr getFirst() const noexcept
214 {
215 const ScopedLockType lock (getLock());
216 return values.getFirst();
217 }
218
224 inline ObjectClassPtr getLast() const noexcept
225 {
226 const ScopedLockType lock (getLock());
227 return values.getLast();
228 }
229
234 inline ObjectClass** getRawDataPointer() const noexcept
235 {
236 return values.begin();
237 }
238
239 //==============================================================================
243 inline ObjectClass** begin() noexcept
244 {
245 return values.begin();
246 }
247
251 inline ObjectClass* const* begin() const noexcept
252 {
253 return values.begin();
254 }
255
259 inline ObjectClass** end() noexcept
260 {
261 return values.end();
262 }
263
267 inline ObjectClass* const* end() const noexcept
268 {
269 return values.end();
270 }
271
275 inline ObjectClass** data() noexcept
276 {
277 return begin();
278 }
279
283 inline ObjectClass* const* data() const noexcept
284 {
285 return begin();
286 }
287
288 //==============================================================================
294 int indexOf (const ObjectClass* objectToLookFor) const noexcept
295 {
296 const ScopedLockType lock (getLock());
297 auto* e = values.begin();
298 auto* endPointer = values.end();
299
300 while (e != endPointer)
301 {
302 if (objectToLookFor == *e)
303 return static_cast<int> (e - values.begin());
304
305 ++e;
306 }
307
308 return -1;
309 }
310
316 int indexOf (const ObjectClassPtr& objectToLookFor) const noexcept { return indexOf (objectToLookFor.get()); }
317
323 bool contains (const ObjectClass* objectToLookFor) const noexcept
324 {
325 const ScopedLockType lock (getLock());
326 auto* e = values.begin();
327 auto* endPointer = values.end();
328
329 while (e != endPointer)
330 {
331 if (objectToLookFor == *e)
332 return true;
333
334 ++e;
335 }
336
337 return false;
338 }
339
345 bool contains (const ObjectClassPtr& objectToLookFor) const noexcept { return contains (objectToLookFor.get()); }
346
354 ObjectClass* add (ObjectClass* newObject)
355 {
356 const ScopedLockType lock (getLock());
357 values.add (newObject);
358
359 if (newObject != nullptr)
360 newObject->incReferenceCount();
361
362 return newObject;
363 }
364
372 ObjectClass* add (const ObjectClassPtr& newObject) { return add (newObject.get()); }
373
387 ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
388 {
389 values.insert (indexToInsertAt, newObject, 1);
390
391 if (newObject != nullptr)
392 newObject->incReferenceCount();
393
394 return newObject;
395 }
396
410 ObjectClass* insert (int indexToInsertAt, const ObjectClassPtr& newObject) { return insert (indexToInsertAt, newObject.get()); }
411
420 bool addIfNotAlreadyThere (ObjectClass* newObject)
421 {
422 const ScopedLockType lock (getLock());
423
424 if (contains (newObject))
425 return false;
426
427 add (newObject);
428 return true;
429 }
430
440
453 void set (int indexToChange, ObjectClass* newObject)
454 {
455 if (indexToChange >= 0)
456 {
457 const ScopedLockType lock (getLock());
458
459 if (newObject != nullptr)
460 newObject->incReferenceCount();
461
462 if (indexToChange < values.size())
463 {
464 auto* e = values[indexToChange];
465 values[indexToChange] = newObject;
466 releaseObject (e);
467 }
468 else
469 {
470 values.add (newObject);
471 }
472 }
473 }
474
488
499 int startIndex = 0,
500 int numElementsToAdd = -1) noexcept
501 {
502 const ScopedLockType lock1 (arrayToAddFrom.getLock());
503
504 {
505 const ScopedLockType lock2 (getLock());
506
507 auto numElementsAdded = values.addArray (arrayToAddFrom.values, startIndex, numElementsToAdd);
508 auto** e = values.end();
509
510 for (int i = 0; i < numElementsAdded; ++i)
511 (*(--e))->incReferenceCount();
512 }
513 }
514
527 template <class ElementComparator>
528 int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
529 {
530 const ScopedLockType lock (getLock());
531 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
532 insert (index, newObject);
533 return index;
534 }
535
541 template <class ElementComparator>
542 void addOrReplaceSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
543 {
544 const ScopedLockType lock (getLock());
545 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
546
547 if (index > 0 && comparator.compareElements (newObject, values[index - 1]) == 0)
548 set (index - 1, newObject); // replace an existing object that matches
549 else
550 insert (index, newObject); // no match, so insert the new one
551 }
552
565 template <class ElementComparator>
566 int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept;
567
568 //==============================================================================
583 {
584 const ScopedLockType lock (getLock());
585
586 if (isPositiveAndBelow (indexToRemove, values.size()))
587 {
588 auto* e = *(values.begin() + indexToRemove);
589 values.removeElements (indexToRemove, 1);
590 releaseObject (e);
591
592 if ((values.size() << 1) < values.capacity())
594 }
595 }
596
607 {
609 const ScopedLockType lock (getLock());
610
611 if (isPositiveAndBelow (indexToRemove, values.size()))
612 {
613 auto* e = *(values.begin() + indexToRemove);
614 removedItem = e;
615 values.removeElements (indexToRemove, 1);
616 releaseObject (e);
617
618 if ((values.size() << 1) < values.capacity())
620 }
621
622 return removedItem;
623 }
624
633 void removeObject (ObjectClass* objectToRemove)
634 {
635 const ScopedLockType lock (getLock());
637 }
638
648
664 void removeRange (int startIndex,
665 int numberToRemove)
666 {
667 const ScopedLockType lock (getLock());
668 startIndex = jlimit (0, values.size(), startIndex);
669 auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
670 numberToRemove = endIndex - startIndex;
671
672 if (numberToRemove > 0)
673 {
675 objectsToRemove.addArray (values.begin() + startIndex, numberToRemove);
676
677 values.removeElements (startIndex, numberToRemove);
678
679 for (auto& o : objectsToRemove)
680 releaseObject (o);
681
682 if ((values.size() << 1) < values.capacity())
684 }
685 }
686
696 {
697 const ScopedLockType lock (getLock());
698
699 if (howManyToRemove > values.size())
700 howManyToRemove = values.size();
701
702 while (--howManyToRemove >= 0)
703 remove (values.size() - 1);
704 }
705
711 void swap (int index1, int index2) noexcept
712 {
713 const ScopedLockType lock (getLock());
714
715 if (isPositiveAndBelow (index1, values.size())
716 && isPositiveAndBelow (index2, values.size()))
717 {
718 std::swap (values[index1], values[index2]);
719 }
720 }
721
735 void move (int currentIndex, int newIndex) noexcept
736 {
737 if (currentIndex != newIndex)
738 {
739 const ScopedLockType lock (getLock());
740 values.move (currentIndex, newIndex);
741 }
742 }
743
744 //==============================================================================
750 template <class OtherArrayType>
752 {
753 const ScopedLockType lock1 (getLock());
754 const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
755 values.swapWith (otherArray.values);
756 }
757
758 //==============================================================================
763 bool operator== (const ReferenceCountedArray& other) const noexcept
764 {
765 const ScopedLockType lock2 (other.getLock());
766 const ScopedLockType lock1 (getLock());
767 return values == other.values;
768 }
769
778
779 //==============================================================================
806 template <class ElementComparator>
807 void sort (ElementComparator& comparator, bool retainOrderOfEquivalentItems = false) noexcept;
808
809 //==============================================================================
817 {
818 const ScopedLockType lock (getLock());
819 values.shrinkToNoMoreThan (values.size());
820 }
821
829 {
830 const ScopedLockType lock (getLock());
831 values.ensureAllocatedSize (minNumElements);
832 }
833
834 //==============================================================================
839 inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
840
842 using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
843
844 //==============================================================================
845 #ifndef DOXYGEN
846 [[deprecated ("This method has been replaced by a more flexible templated version and renamed "
847 "to swapWith to be more consistent with the names used in other classes.")]]
849 #endif
850
851private:
852 //==============================================================================
854
855 void releaseAllObjects()
856 {
857 auto i = values.size();
858
859 while (--i >= 0)
860 {
861 auto* e = values[i];
862 values.removeElements (i, 1);
863 releaseObject (e);
864 }
865 }
866
867 static void releaseObject (ObjectClass* o)
868 {
869 if (o != nullptr && o->decReferenceCountWithoutDeleting())
870 ContainerDeletePolicy<ObjectClass>::destroy (o);
871 }
872};
873
874//==============================================================================
875template <class ObjectClass, class TypeOfCriticalSectionToUse>
876template <class ElementComparator>
878 [[maybe_unused]] ElementComparator& comparator,
879 const ObjectClass* objectToLookFor) const noexcept
880{
881 const ScopedLockType lock (getLock());
882 int s = 0, e = values.size();
883
884 while (s < e)
885 {
886 if (comparator.compareElements (objectToLookFor, values[s]) == 0)
887 return s;
888
889 auto halfway = (s + e) / 2;
890
891 if (halfway == s)
892 break;
893
894 if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
895 s = halfway;
896 else
897 e = halfway;
898 }
899
900 return -1;
901}
902
903template <class ObjectClass, class TypeOfCriticalSectionToUse>
904template <class ElementComparator>
906 [[maybe_unused]] ElementComparator& comparator,
907 bool retainOrderOfEquivalentItems) noexcept
908{
909 const ScopedLockType lock (getLock());
910 sortArray (comparator, values.begin(), 0, values.size() - 1, retainOrderOfEquivalentItems);
911}
912
913} // namespace juce
A basic object container.
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:56
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition juce_Array.h:583
Holds a list of objects derived from ReferenceCountedObject, or which implement basic reference-count...
ReferenceCountedArray(ReferenceCountedArray &&other) noexcept
Moves from another array.
ObjectClass * add(const ObjectClassPtr &newObject)
Appends a new object to the end of the array.
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
int indexOf(const ObjectClass *objectToLookFor) const noexcept
Finds the index of the first occurrence of an object in the array.
ReferenceCountedArray(const ReferenceCountedArray &other) noexcept
Creates a copy of another array.
int size() const noexcept
Returns the current number of objects in the array.
void removeLast(int howManyToRemove=1)
Removes the last n objects from the array.
ObjectClass *const * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
void minimiseStorageOverheads() noexcept
Reduces the amount of storage being used by the array.
void set(int indexToChange, ObjectClass *newObject)
Replaces an object in the array with a different one.
ObjectClass *const * begin() const noexcept
Returns a pointer to the first element in the array.
ObjectClass * insert(int indexToInsertAt, const ObjectClassPtr &newObject)
Inserts a new object into the array at the given index.
ReferenceCountedArray()=default
Creates an empty array.
bool operator!=(const ReferenceCountedArray< ObjectClass, TypeOfCriticalSectionToUse > &other) const noexcept
Compares this array to another one.
int indexOfSorted(ElementComparator &comparator, const ObjectClass *objectToLookFor) const noexcept
Finds the index of an object in the array, assuming that the array is sorted.
typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
Returns the type of scoped lock to use for locking this array.
bool addIfNotAlreadyThere(ObjectClass *newObject)
Appends a new object at the end of the array as long as the array doesn't already contain it.
ObjectClassPtr operator[](int index) const noexcept
Returns a pointer to the object at this index in the array.
void remove(int indexToRemove)
Removes an object from the array.
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) noexcept
Sorts the elements in the array.
ReferenceCountedArray(const ReferenceCountedArray< OtherObjectClass, OtherCriticalSection > &other) noexcept
Creates a copy of another array.
bool operator==(const ReferenceCountedArray &other) const noexcept
Compares this array to another one.
void removeObject(ObjectClass *objectToRemove)
Removes the first occurrence of a specified object from the array.
ObjectClass * getObjectPointer(int index) const noexcept
Returns a raw pointer to the object at this index in the array.
void swap(int index1, int index2) noexcept
Swaps a pair of objects in the array.
ObjectClassPtr getFirst() const noexcept
Returns a pointer to the first object in the array.
void ensureStorageAllocated(const int minNumElements)
Increases the array's internal storage to hold a minimum number of elements.
void clearQuick()
Removes all objects from the array without freeing the array's allocated storage.
void set(int indexToChange, const ObjectClassPtr &newObject)
Replaces an object in the array with a different one.
ObjectClass *const * data() const noexcept
Returns a pointer to the first element in the array.
const TypeOfCriticalSectionToUse & getLock() const noexcept
Returns the CriticalSection that locks this array.
ObjectClassPtr getUnchecked(int index) const noexcept
Returns a pointer to the object at this index in the array, without checking whether the index is in-...
ObjectClass ** begin() noexcept
Returns a pointer to the first element in the array.
void addOrReplaceSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Inserts or replaces an object in the array, assuming it is sorted.
bool contains(const ObjectClass *objectToLookFor) const noexcept
Returns true if the array contains a specified object.
void removeRange(int startIndex, int numberToRemove)
Removes a range of objects from the array.
ObjectClass * getObjectPointerUnchecked(int index) const noexcept
Returns a raw pointer to the object at this index in the array, without checking whether the index is...
void move(int currentIndex, int newIndex) noexcept
Moves one of the objects to a different position.
ObjectClassPtr removeAndReturn(int indexToRemove)
Removes and returns an object from the array.
ReferenceCountedArray & operator=(const ReferenceCountedArray &other) noexcept
Copies another array into this one.
ObjectClass ** end() noexcept
Returns a pointer to the element which follows the last element in the array.
void clear()
Removes all objects from the array.
ObjectClass ** getRawDataPointer() const noexcept
Returns a pointer to the actual array data.
bool contains(const ObjectClassPtr &objectToLookFor) const noexcept
Returns true if the array contains a specified object.
ObjectClass ** data() noexcept
Returns a pointer to the first element in the array.
void swapWith(OtherArrayType &otherArray) noexcept
This swaps the contents of this array with those of another array.
bool addIfNotAlreadyThere(const ObjectClassPtr &newObject)
Appends a new object at the end of the array as long as the array doesn't already contain it.
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Inserts a new object into the array assuming that the array is sorted.
int indexOf(const ObjectClassPtr &objectToLookFor) const noexcept
Finds the index of the first occurrence of an object in the array.
ObjectClassPtr getLast() const noexcept
Returns a pointer to the last object in the array.
void addArray(const ReferenceCountedArray &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1) noexcept
Adds elements from another array to the end of this array.
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
Inserts a new object into the array at the given index.
ObjectClass * add(ObjectClass *newObject)
Appends a new object to the end of the array.
void removeObject(const ObjectClassPtr &objectToRemove)
Removes the first occurrence of a specified object from the array.
A smart-pointer class which points to a reference-counted object.
JUCE Namespace.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
T swap(T... args)