OpenShot Library | OpenShotAudio 0.2.2
juce_ReferenceCountedArray.h
1
2/** @weakgroup juce_core-containers
3 * @{
4 */
5/*
6 ==============================================================================
7
8 This file is part of the JUCE library.
9 Copyright (c) 2017 - ROLI Ltd.
10
11 JUCE is an open source library subject to commercial or open-source
12 licensing.
13
14 The code included in this file is provided under the terms of the ISC license
15 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16 To use, copy, modify, and/or distribute this software for any purpose with or
17 without fee is hereby granted provided that the above copyright notice and
18 this permission notice appear in all copies.
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
30//==============================================================================
31/**
32 Holds a list of objects derived from ReferenceCountedObject, or which implement basic
33 reference-count handling methods.
34
35 The template parameter specifies the class of the object you want to point to - the easiest
36 way to make a class reference-countable is to simply make it inherit from ReferenceCountedObject
37 or SingleThreadedReferenceCountedObject, but if you need to, you can roll your own reference-countable
38 class by implementing a set of methods called incReferenceCount(), decReferenceCount(), and
39 decReferenceCountWithoutDeleting(). See ReferenceCountedObject for examples of how these methods
40 should behave.
41
42 A ReferenceCountedArray holds objects derived from ReferenceCountedObject,
43 and takes care of incrementing and decrementing their ref counts when they
44 are added and removed from the array.
45
46 To make all the array's methods thread-safe, pass in "CriticalSection" as the templated
47 TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection.
48
49 @see Array, OwnedArray, StringArray
50
51 @tags{Core}
52*/
53template <class ObjectClass, class TypeOfCriticalSectionToUse = DummyCriticalSection>
55{
56public:
58
59 //==============================================================================
60 /** Creates an empty array.
61 @see ReferenceCountedObject, Array, OwnedArray
62 */
64
65 /** Creates a copy of another array */
67 {
68 const ScopedLockType lock (other.getLock());
69 values.addArray (other.begin(), other.size());
70
71 for (auto* o : *this)
72 if (o != nullptr)
73 o->incReferenceCount();
74 }
75
76 /** Moves from another array */
78 : values (std::move (other.values))
79 {
80 }
81
82 /** Creates a copy of another array */
83 template <class OtherObjectClass, class OtherCriticalSection>
85 {
87 values.addArray (other.begin(), other.size());
88
89 for (auto* o : *this)
90 if (o != nullptr)
91 o->incReferenceCount();
92 }
93
94 /** Copies another array into this one.
95 Any existing objects in this array will first be released.
96 */
98 {
99 releaseAllObjects();
100 auto otherCopy = other;
101 swapWith (otherCopy);
102 return *this;
103 }
104
105 /** Copies another array into this one.
106 Any existing objects in this array will first be released.
107 */
108 template <class OtherObjectClass>
110 {
111 auto otherCopy = other;
112 swapWith (otherCopy);
113 return *this;
114 }
115
116 /** Moves from another array */
118 {
119 releaseAllObjects();
120 values = std::move (other.values);
121 return *this;
122 }
123
124 /** Destructor.
125 Any objects in the array will be released, and may be deleted if not referenced from elsewhere.
126 */
128 {
129 releaseAllObjects();
130 }
131
132 //==============================================================================
133 /** Removes all objects from the array.
134 Any objects in the array whose reference counts drop to zero will be deleted.
135 */
136 void clear()
137 {
138 const ScopedLockType lock (getLock());
139 clearQuick();
140 values.setAllocatedSize (0);
141 }
142
143 /** Removes all objects from the array without freeing the array's allocated storage.
144 Any objects in the array that whose reference counts drop to zero will be deleted.
145 @see clear
146 */
148 {
149 const ScopedLockType lock (getLock());
150 releaseAllObjects();
151 }
152
153 /** Returns the current number of objects in the array. */
154 inline int size() const noexcept
155 {
156 return values.size();
157 }
158
159 /** Returns true if the array is empty, false otherwise. */
160 inline bool isEmpty() const noexcept
161 {
162 return size() == 0;
163 }
164
165 /** Returns a pointer to the object at this index in the array.
166
167 If the index is out-of-range, this will return a null pointer, (and
168 it could be null anyway, because it's ok for the array to hold null
169 pointers as well as objects).
170
171 @see getUnchecked
172 */
173 inline ObjectClassPtr operator[] (int index) const noexcept
174 {
175 return ObjectClassPtr (getObjectPointer (index));
176 }
177
178 /** Returns a pointer to the object at this index in the array, without checking
179 whether the index is in-range.
180
181 This is a faster and less safe version of operator[] which doesn't check the index passed in, so
182 it can be used when you're sure the index is always going to be legal.
183 */
184 inline ObjectClassPtr getUnchecked (int index) const noexcept
185 {
187 }
188
189 /** Returns a raw pointer to the object at this index in the array.
190
191 If the index is out-of-range, this will return a null pointer, (and
192 it could be null anyway, because it's ok for the array to hold null
193 pointers as well as objects).
194
195 @see getUnchecked
196 */
197 inline ObjectClass* getObjectPointer (int index) const noexcept
198 {
199 const ScopedLockType lock (getLock());
200 return values.getValueWithDefault (index);
201 }
202
203 /** Returns a raw pointer to the object at this index in the array, without checking
204 whether the index is in-range.
205 */
206 inline ObjectClass* getObjectPointerUnchecked (int index) const noexcept
207 {
208 const ScopedLockType lock (getLock());
209 return values[index];
210 }
211
212 /** Returns a pointer to the first object in the array.
213
214 This will return a null pointer if the array's empty.
215 @see getLast
216 */
217 inline ObjectClassPtr getFirst() const noexcept
218 {
219 const ScopedLockType lock (getLock());
220 return values.getFirst();
221 }
222
223 /** Returns a pointer to the last object in the array.
224
225 This will return a null pointer if the array's empty.
226 @see getFirst
227 */
228 inline ObjectClassPtr getLast() const noexcept
229 {
230 const ScopedLockType lock (getLock());
231 return values.getLast();
232 }
233
234 /** Returns a pointer to the actual array data.
235 This pointer will only be valid until the next time a non-const method
236 is called on the array.
237 */
238 inline ObjectClass** getRawDataPointer() const noexcept
239 {
240 return values.begin();
241 }
242
243 //==============================================================================
244 /** Returns a pointer to the first element in the array.
245 This method is provided for compatibility with standard C++ iteration mechanisms.
246 */
247 inline ObjectClass** begin() noexcept
248 {
249 return values.begin();
250 }
251
252 /** Returns a pointer to the first element in the array.
253 This method is provided for compatibility with standard C++ iteration mechanisms.
254 */
255 inline ObjectClass* const* begin() const noexcept
256 {
257 return values.begin();
258 }
259
260 /** Returns a pointer to the element which follows the last element in the array.
261 This method is provided for compatibility with standard C++ iteration mechanisms.
262 */
263 inline ObjectClass** end() noexcept
264 {
265 return values.end();
266 }
267
268 /** Returns a pointer to the element which follows the last element in the array.
269 This method is provided for compatibility with standard C++ iteration mechanisms.
270 */
271 inline ObjectClass* const* end() const noexcept
272 {
273 return values.end();
274 }
275
276 /** Returns a pointer to the first element in the array.
277 This method is provided for compatibility with the standard C++ containers.
278 */
279 inline ObjectClass** data() noexcept
280 {
281 return begin();
282 }
283
284 /** Returns a pointer to the first element in the array.
285 This method is provided for compatibility with the standard C++ containers.
286 */
287 inline ObjectClass* const* data() const noexcept
288 {
289 return begin();
290 }
291
292 //==============================================================================
293 /** Finds the index of the first occurrence of an object in the array.
294
295 @param objectToLookFor the object to look for
296 @returns the index at which the object was found, or -1 if it's not found
297 */
298 int indexOf (const ObjectClass* objectToLookFor) const noexcept
299 {
300 const ScopedLockType lock (getLock());
301 auto* e = values.begin();
302 auto* endPointer = values.end();
303
304 while (e != endPointer)
305 {
306 if (objectToLookFor == *e)
307 return static_cast<int> (e - values.begin());
308
309 ++e;
310 }
311
312 return -1;
313 }
314
315 /** Finds the index of the first occurrence of an object in the array.
316
317 @param objectToLookFor the object to look for
318 @returns the index at which the object was found, or -1 if it's not found
319 */
320 int indexOf (const ObjectClassPtr& objectToLookFor) const noexcept { return indexOf (objectToLookFor.get()); }
321
322 /** Returns true if the array contains a specified object.
323
324 @param objectToLookFor the object to look for
325 @returns true if the object is in the array
326 */
327 bool contains (const ObjectClass* objectToLookFor) const noexcept
328 {
329 const ScopedLockType lock (getLock());
330 auto* e = values.begin();
331 auto* endPointer = values.end();
332
333 while (e != endPointer)
334 {
335 if (objectToLookFor == *e)
336 return true;
337
338 ++e;
339 }
340
341 return false;
342 }
343
344 /** Returns true if the array contains a specified object.
345
346 @param objectToLookFor the object to look for
347 @returns true if the object is in the array
348 */
349 bool contains (const ObjectClassPtr& objectToLookFor) const noexcept { return contains (objectToLookFor.get()); }
350
351 /** Appends a new object to the end of the array.
352
353 This will increase the new object's reference count.
354
355 @param newObject the new object to add to the array
356 @see set, insert, addIfNotAlreadyThere, addSorted, addArray
357 */
358 ObjectClass* add (ObjectClass* newObject)
359 {
360 const ScopedLockType lock (getLock());
361 values.add (newObject);
362
363 if (newObject != nullptr)
364 newObject->incReferenceCount();
365
366 return newObject;
367 }
368
369 /** Appends a new object to the end of the array.
370
371 This will increase the new object's reference count.
372
373 @param newObject the new object to add to the array
374 @see set, insert, addIfNotAlreadyThere, addSorted, addArray
375 */
376 ObjectClass* add (const ObjectClassPtr& newObject) { return add (newObject.get()); }
377
378 /** Inserts a new object into the array at the given index.
379
380 If the index is less than 0 or greater than the size of the array, the
381 element will be added to the end of the array.
382 Otherwise, it will be inserted into the array, moving all the later elements
383 along to make room.
384
385 This will increase the new object's reference count.
386
387 @param indexToInsertAt the index at which the new element should be inserted
388 @param newObject the new object to add to the array
389 @see add, addSorted, addIfNotAlreadyThere, set
390 */
391 ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
392 {
393 values.insert (indexToInsertAt, newObject, 1);
394
395 if (newObject != nullptr)
396 newObject->incReferenceCount();
397
398 return newObject;
399 }
400
401 /** Inserts a new object into the array at the given index.
402
403 If the index is less than 0 or greater than the size of the array, the
404 element will be added to the end of the array.
405 Otherwise, it will be inserted into the array, moving all the later elements
406 along to make room.
407
408 This will increase the new object's reference count.
409
410 @param indexToInsertAt the index at which the new element should be inserted
411 @param newObject the new object to add to the array
412 @see add, addSorted, addIfNotAlreadyThere, set
413 */
414 ObjectClass* insert (int indexToInsertAt, const ObjectClassPtr& newObject) { return insert (indexToInsertAt, newObject.get()); }
415
416 /** Appends a new object at the end of the array as long as the array doesn't
417 already contain it.
418
419 If the array already contains a matching object, nothing will be done.
420
421 @param newObject the new object to add to the array
422 @returns true if the object has been added, false otherwise
423 */
424 bool addIfNotAlreadyThere (ObjectClass* newObject)
425 {
426 const ScopedLockType lock (getLock());
427
428 if (contains (newObject))
429 return false;
430
431 add (newObject);
432 return true;
433 }
434
435 /** Appends a new object at the end of the array as long as the array doesn't
436 already contain it.
437
438 If the array already contains a matching object, nothing will be done.
439
440 @param newObject the new object to add to the array
441 @returns true if the object has been added, false otherwise
442 */
443 bool addIfNotAlreadyThere (const ObjectClassPtr& newObject) { return addIfNotAlreadyThere (newObject.get()); }
444
445 /** Replaces an object in the array with a different one.
446
447 If the index is less than zero, this method does nothing.
448 If the index is beyond the end of the array, the new object is added to the end of the array.
449
450 The object being added has its reference count increased, and if it's replacing
451 another object, then that one has its reference count decreased, and may be deleted.
452
453 @param indexToChange the index whose value you want to change
454 @param newObject the new value to set for this index.
455 @see add, insert, remove
456 */
457 void set (int indexToChange, ObjectClass* newObject)
458 {
459 if (indexToChange >= 0)
460 {
461 const ScopedLockType lock (getLock());
462
463 if (newObject != nullptr)
464 newObject->incReferenceCount();
465
466 if (indexToChange < values.size())
467 {
468 auto* e = values[indexToChange];
469 values[indexToChange] = newObject;
470 releaseObject (e);
471 }
472 else
473 {
474 values.add (newObject);
475 }
476 }
477 }
478
479 /** Replaces an object in the array with a different one.
480
481 If the index is less than zero, this method does nothing.
482 If the index is beyond the end of the array, the new object is added to the end of the array.
483
484 The object being added has its reference count increased, and if it's replacing
485 another object, then that one has its reference count decreased, and may be deleted.
486
487 @param indexToChange the index whose value you want to change
488 @param newObject the new value to set for this index.
489 @see add, insert, remove
490 */
491 void set (int indexToChange, const ObjectClassPtr& newObject) { set (indexToChange, newObject.get()); }
492
493 /** Adds elements from another array to the end of this array.
494
495 @param arrayToAddFrom the array from which to copy the elements
496 @param startIndex the first element of the other array to start copying from
497 @param numElementsToAdd how many elements to add from the other array. If this
498 value is negative or greater than the number of available elements,
499 all available elements will be copied.
500 @see add
501 */
502 void addArray (const ReferenceCountedArray& arrayToAddFrom,
503 int startIndex = 0,
504 int numElementsToAdd = -1) noexcept
505 {
506 const ScopedLockType lock1 (arrayToAddFrom.getLock());
507
508 {
509 const ScopedLockType lock2 (getLock());
510
511 auto numElementsAdded = values.addArray (arrayToAddFrom.values, startIndex, numElementsToAdd);
512 auto** e = values.end();
513
514 for (int i = 0; i < numElementsAdded; ++i)
515 (*(--e))->incReferenceCount();
516 }
517 }
518
519 /** Inserts a new object into the array assuming that the array is sorted.
520
521 This will use a comparator to find the position at which the new object
522 should go. If the array isn't sorted, the behaviour of this
523 method will be unpredictable.
524
525 @param comparator the comparator object to use to compare the elements - see the
526 sort() method for details about this object's form
527 @param newObject the new object to insert to the array
528 @returns the index at which the new object was added
529 @see add, sort
530 */
531 template <class ElementComparator>
532 int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
533 {
534 const ScopedLockType lock (getLock());
535 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
536 insert (index, newObject);
537 return index;
538 }
539
540 /** Inserts or replaces an object in the array, assuming it is sorted.
541
542 This is similar to addSorted, but if a matching element already exists, then it will be
543 replaced by the new one, rather than the new one being added as well.
544 */
545 template <class ElementComparator>
546 void addOrReplaceSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
547 {
548 const ScopedLockType lock (getLock());
549 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
550
551 if (index > 0 && comparator.compareElements (newObject, values[index - 1]) == 0)
552 set (index - 1, newObject); // replace an existing object that matches
553 else
554 insert (index, newObject); // no match, so insert the new one
555 }
556
557 /** Finds the index of an object in the array, assuming that the array is sorted.
558
559 This will use a comparator to do a binary-chop to find the index of the given
560 element, if it exists. If the array isn't sorted, the behaviour of this
561 method will be unpredictable.
562
563 @param comparator the comparator to use to compare the elements - see the sort()
564 method for details about the form this object should take
565 @param objectToLookFor the object to search for
566 @returns the index of the element, or -1 if it's not found
567 @see addSorted, sort
568 */
569 template <class ElementComparator>
570 int indexOfSorted (ElementComparator& comparator,
571 const ObjectClass* objectToLookFor) const noexcept
572 {
573 ignoreUnused (comparator);
574 const ScopedLockType lock (getLock());
575 int s = 0, e = values.size();
576
577 while (s < e)
578 {
579 if (comparator.compareElements (objectToLookFor, values[s]) == 0)
580 return s;
581
582 auto halfway = (s + e) / 2;
583
584 if (halfway == s)
585 break;
586
587 if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
588 s = halfway;
589 else
590 e = halfway;
591 }
592
593 return -1;
594 }
595
596 //==============================================================================
597 /** Removes an object from the array.
598
599 This will remove the object at a given index and move back all the
600 subsequent objects to close the gap.
601
602 If the index passed in is out-of-range, nothing will happen.
603
604 The object that is removed will have its reference count decreased,
605 and may be deleted if not referenced from elsewhere.
606
607 @param indexToRemove the index of the element to remove
608 @see removeObject, removeRange
609 */
610 void remove (int indexToRemove)
611 {
612 const ScopedLockType lock (getLock());
613
614 if (isPositiveAndBelow (indexToRemove, values.size()))
615 {
616 auto* e = *(values.begin() + indexToRemove);
617 values.removeElements (indexToRemove, 1);
618 releaseObject (e);
619
620 if ((values.size() << 1) < values.capacity())
622 }
623 }
624
625 /** Removes and returns an object from the array.
626
627 This will remove the object at a given index and return it, moving back all
628 the subsequent objects to close the gap. If the index passed in is out-of-range,
629 nothing will happen and a null pointer will be returned.
630
631 @param indexToRemove the index of the element to remove
632 @see remove, removeObject, removeRange
633 */
634 ObjectClassPtr removeAndReturn (int indexToRemove)
635 {
636 ObjectClassPtr removedItem;
637 const ScopedLockType lock (getLock());
638
639 if (isPositiveAndBelow (indexToRemove, values.size()))
640 {
641 auto* e = *(values.begin() + indexToRemove);
642 removedItem = e;
643 values.removeElements (indexToRemove, 1);
644 releaseObject (e);
645
646 if ((values.size() << 1) < values.capacity())
648 }
649
650 return removedItem;
651 }
652
653 /** Removes the first occurrence of a specified object from the array.
654
655 If the item isn't found, no action is taken. If it is found, it is
656 removed and has its reference count decreased.
657
658 @param objectToRemove the object to try to remove
659 @see remove, removeRange
660 */
661 void removeObject (ObjectClass* objectToRemove)
662 {
663 const ScopedLockType lock (getLock());
664 remove (indexOf (objectToRemove));
665 }
666
667 /** Removes the first occurrence of a specified object from the array.
668
669 If the item isn't found, no action is taken. If it is found, it is
670 removed and has its reference count decreased.
671
672 @param objectToRemove the object to try to remove
673 @see remove, removeRange
674 */
675 void removeObject (const ObjectClassPtr& objectToRemove) { removeObject (objectToRemove.get()); }
676
677 /** Removes a range of objects from the array.
678
679 This will remove a set of objects, starting from the given index,
680 and move any subsequent elements down to close the gap.
681
682 If the range extends beyond the bounds of the array, it will
683 be safely clipped to the size of the array.
684
685 The objects that are removed will have their reference counts decreased,
686 and may be deleted if not referenced from elsewhere.
687
688 @param startIndex the index of the first object to remove
689 @param numberToRemove how many objects should be removed
690 @see remove, removeObject
691 */
692 void removeRange (int startIndex,
693 int numberToRemove)
694 {
695 const ScopedLockType lock (getLock());
696 startIndex = jlimit (0, values.size(), startIndex);
697 auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
698 numberToRemove = endIndex - startIndex;
699
700 if (numberToRemove > 0)
701 {
702 Array<ObjectClass*> objectsToRemove;
703 objectsToRemove.addArray (values.begin() + startIndex, numberToRemove);
704
705 values.removeElements (startIndex, numberToRemove);
706
707 for (auto& o : objectsToRemove)
708 releaseObject (o);
709
710 if ((values.size() << 1) < values.capacity())
712 }
713 }
714
715 /** Removes the last n objects from the array.
716
717 The objects that are removed will have their reference counts decreased,
718 and may be deleted if not referenced from elsewhere.
719
720 @param howManyToRemove how many objects to remove from the end of the array
721 @see remove, removeObject, removeRange
722 */
723 void removeLast (int howManyToRemove = 1)
724 {
725 const ScopedLockType lock (getLock());
726
727 if (howManyToRemove > values.size())
728 howManyToRemove = values.size();
729
730 while (--howManyToRemove >= 0)
731 remove (values.size() - 1);
732 }
733
734 /** Swaps a pair of objects in the array.
735
736 If either of the indexes passed in is out-of-range, nothing will happen,
737 otherwise the two objects at these positions will be exchanged.
738 */
739 void swap (int index1, int index2) noexcept
740 {
741 const ScopedLockType lock (getLock());
742
743 if (isPositiveAndBelow (index1, values.size())
744 && isPositiveAndBelow (index2, values.size()))
745 {
746 std::swap (values[index1], values[index2]);
747 }
748 }
749
750 /** Moves one of the objects to a different position.
751
752 This will move the object to a specified index, shuffling along
753 any intervening elements as required.
754
755 So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
756 move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
757
758 @param currentIndex the index of the object to be moved. If this isn't a
759 valid index, then nothing will be done
760 @param newIndex the index at which you'd like this object to end up. If this
761 is less than zero, it will be moved to the end of the array
762 */
763 void move (int currentIndex, int newIndex) noexcept
764 {
765 if (currentIndex != newIndex)
766 {
767 const ScopedLockType lock (getLock());
768 values.move (currentIndex, newIndex);
769 }
770 }
771
772 //==============================================================================
773 /** This swaps the contents of this array with those of another array.
774
775 If you need to exchange two arrays, this is vastly quicker than using copy-by-value
776 because it just swaps their internal pointers.
777 */
778 template <class OtherArrayType>
779 void swapWith (OtherArrayType& otherArray) noexcept
780 {
781 const ScopedLockType lock1 (getLock());
782 const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
783 values.swapWith (otherArray.values);
784 }
785
786 //==============================================================================
787 /** Compares this array to another one.
788
789 @returns true only if the other array contains the same objects in the same order
790 */
791 bool operator== (const ReferenceCountedArray& other) const noexcept
792 {
793 const ScopedLockType lock2 (other.getLock());
794 const ScopedLockType lock1 (getLock());
795 return values == other.values;
796 }
797
798 /** Compares this array to another one.
799
800 @see operator==
801 */
803 {
804 return ! operator== (other);
805 }
806
807 //==============================================================================
808 /** Sorts the elements in the array.
809
810 This will use a comparator object to sort the elements into order. The object
811 passed must have a method of the form:
812 @code
813 int compareElements (ElementType first, ElementType second);
814 @endcode
815
816 ..and this method must return:
817 - a value of < 0 if the first comes before the second
818 - a value of 0 if the two objects are equivalent
819 - a value of > 0 if the second comes before the first
820
821 To improve performance, the compareElements() method can be declared as static or const.
822
823 @param comparator the comparator to use for comparing elements.
824 @param retainOrderOfEquivalentItems if this is true, then items
825 which the comparator says are equivalent will be
826 kept in the order in which they currently appear
827 in the array. This is slower to perform, but may
828 be important in some cases. If it's false, a faster
829 algorithm is used, but equivalent elements may be
830 rearranged.
831
832 @see sortArray
833 */
834 template <class ElementComparator>
835 void sort (ElementComparator& comparator,
836 bool retainOrderOfEquivalentItems = false) noexcept
837 {
838 // If you pass in an object with a static compareElements() method, this
839 // avoids getting warning messages about the parameter being unused
840 ignoreUnused (comparator);
841
842 const ScopedLockType lock (getLock());
843 sortArray (comparator, values.begin(), 0, values.size() - 1, retainOrderOfEquivalentItems);
844 }
845
846 //==============================================================================
847 /** Reduces the amount of storage being used by the array.
848
849 Arrays typically allocate slightly more storage than they need, and after
850 removing elements, they may have quite a lot of unused space allocated.
851 This method will reduce the amount of allocated storage to a minimum.
852 */
854 {
855 const ScopedLockType lock (getLock());
856 values.shrinkToNoMoreThan (values.size());
857 }
858
859 /** Increases the array's internal storage to hold a minimum number of elements.
860
861 Calling this before adding a large known number of elements means that
862 the array won't have to keep dynamically resizing itself as the elements
863 are added, and it'll therefore be more efficient.
864 */
865 void ensureStorageAllocated (const int minNumElements)
866 {
867 const ScopedLockType lock (getLock());
868 values.ensureAllocatedSize (minNumElements);
869 }
870
871 //==============================================================================
872 /** Returns the CriticalSection that locks this array.
873 To lock, you can call getLock().enter() and getLock().exit(), or preferably use
874 an object of ScopedLockType as an RAII lock for it.
875 */
876 inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
877
878 /** Returns the type of scoped lock to use for locking this array */
879 using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
880
881 //==============================================================================
882 #ifndef DOXYGEN
883 // Note that the swapWithArray method has been replaced by a more flexible templated version,
884 // and renamed "swapWith" to be more consistent with the names used in other classes.
885 JUCE_DEPRECATED_WITH_BODY (void swapWithArray (ReferenceCountedArray& other) noexcept, { swapWith (other); })
886 #endif
887
888private:
889 //==============================================================================
891
892 void releaseAllObjects()
893 {
894 auto i = values.size();
895
896 while (--i >= 0)
897 {
898 auto* e = values[i];
899 values.removeElements (i, 1);
900 releaseObject (e);
901 }
902 }
903
904 static void releaseObject (ObjectClass* o)
905 {
906 if (o != nullptr && o->decReferenceCountWithoutDeleting())
907 ContainerDeletePolicy<ObjectClass>::destroy (o);
908 }
909};
910
911} // namespace juce
912
913/** @}*/
A basic object container.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:60
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition: juce_Array.h:587
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.
ReferencedType * get() const noexcept
Returns the object that this pointer references.