OpenShot Library | libopenshot-audio  0.2.0
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 
27 namespace 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 */
53 template <class ObjectClass, class TypeOfCriticalSectionToUse = DummyCriticalSection>
55 {
56 public:
58 
59  //==============================================================================
60  /** Creates an empty array.
61  @see ReferenceCountedObject, Array, OwnedArray
62  */
63  ReferenceCountedArray() = default;
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  */
147  void clearQuick()
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  {
186  return ObjectClassPtr (getObjectPointerUnchecked (index));
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() const noexcept
248  {
249  return values.begin();
250  }
251 
252  /** Returns a pointer to the element which follows the last element in the array.
253  This method is provided for compatibility with standard C++ iteration mechanisms.
254  */
255  inline ObjectClass** end() const noexcept
256  {
257  return values.end();
258  }
259 
260  /** Returns a pointer to the first element in the array.
261  This method is provided for compatibility with the standard C++ containers.
262  */
263  inline ObjectClass** data() const noexcept
264  {
265  return begin();
266  }
267 
268  //==============================================================================
269  /** Finds the index of the first occurrence of an object in the array.
270 
271  @param objectToLookFor the object to look for
272  @returns the index at which the object was found, or -1 if it's not found
273  */
274  int indexOf (const ObjectClass* objectToLookFor) const noexcept
275  {
276  const ScopedLockType lock (getLock());
277  auto** e = values.begin();
278  auto** endPointer = values.end();
279 
280  while (e != endPointer)
281  {
282  if (objectToLookFor == *e)
283  return static_cast<int> (e - values.begin());
284 
285  ++e;
286  }
287 
288  return -1;
289  }
290 
291  /** Finds the index of the first occurrence of an object in the array.
292 
293  @param objectToLookFor the object to look for
294  @returns the index at which the object was found, or -1 if it's not found
295  */
296  int indexOf (const ObjectClassPtr& objectToLookFor) const noexcept { return indexOf (objectToLookFor.get()); }
297 
298  /** Returns true if the array contains a specified object.
299 
300  @param objectToLookFor the object to look for
301  @returns true if the object is in the array
302  */
303  bool contains (const ObjectClass* objectToLookFor) const noexcept
304  {
305  const ScopedLockType lock (getLock());
306  auto** e = values.begin();
307  auto** endPointer = values.end();
308 
309  while (e != endPointer)
310  {
311  if (objectToLookFor == *e)
312  return true;
313 
314  ++e;
315  }
316 
317  return false;
318  }
319 
320  /** Returns true if the array contains a specified object.
321 
322  @param objectToLookFor the object to look for
323  @returns true if the object is in the array
324  */
325  bool contains (const ObjectClassPtr& objectToLookFor) const noexcept { return contains (objectToLookFor.get()); }
326 
327  /** Appends a new object to the end of the array.
328 
329  This will increase the new object's reference count.
330 
331  @param newObject the new object to add to the array
332  @see set, insert, addIfNotAlreadyThere, addSorted, addArray
333  */
334  ObjectClass* add (ObjectClass* newObject)
335  {
336  const ScopedLockType lock (getLock());
337  values.add (newObject);
338 
339  if (newObject != nullptr)
340  newObject->incReferenceCount();
341 
342  return newObject;
343  }
344 
345  /** Appends a new object to the end of the array.
346 
347  This will increase the new object's reference count.
348 
349  @param newObject the new object to add to the array
350  @see set, insert, addIfNotAlreadyThere, addSorted, addArray
351  */
352  ObjectClass* add (const ObjectClassPtr& newObject) { return add (newObject.get()); }
353 
354  /** Inserts a new object into the array at the given index.
355 
356  If the index is less than 0 or greater than the size of the array, the
357  element will be added to the end of the array.
358  Otherwise, it will be inserted into the array, moving all the later elements
359  along to make room.
360 
361  This will increase the new object's reference count.
362 
363  @param indexToInsertAt the index at which the new element should be inserted
364  @param newObject the new object to add to the array
365  @see add, addSorted, addIfNotAlreadyThere, set
366  */
367  ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
368  {
369  values.insert (indexToInsertAt, newObject, 1);
370 
371  if (newObject != nullptr)
372  newObject->incReferenceCount();
373 
374  return newObject;
375  }
376 
377  /** Inserts a new object into the array at the given index.
378 
379  If the index is less than 0 or greater than the size of the array, the
380  element will be added to the end of the array.
381  Otherwise, it will be inserted into the array, moving all the later elements
382  along to make room.
383 
384  This will increase the new object's reference count.
385 
386  @param indexToInsertAt the index at which the new element should be inserted
387  @param newObject the new object to add to the array
388  @see add, addSorted, addIfNotAlreadyThere, set
389  */
390  ObjectClass* insert (int indexToInsertAt, const ObjectClassPtr& newObject) { return insert (indexToInsertAt, newObject.get()); }
391 
392  /** Appends a new object at the end of the array as long as the array doesn't
393  already contain it.
394 
395  If the array already contains a matching object, nothing will be done.
396 
397  @param newObject the new object to add to the array
398  @returns true if the object has been added, false otherwise
399  */
400  bool addIfNotAlreadyThere (ObjectClass* newObject)
401  {
402  const ScopedLockType lock (getLock());
403 
404  if (contains (newObject))
405  return false;
406 
407  add (newObject);
408  return true;
409  }
410 
411  /** Appends a new object at the end of the array as long as the array doesn't
412  already contain it.
413 
414  If the array already contains a matching object, nothing will be done.
415 
416  @param newObject the new object to add to the array
417  @returns true if the object has been added, false otherwise
418  */
419  bool addIfNotAlreadyThere (const ObjectClassPtr& newObject) { return addIfNotAlreadyThere (newObject.get()); }
420 
421  /** Replaces an object in the array with a different one.
422 
423  If the index is less than zero, this method does nothing.
424  If the index is beyond the end of the array, the new object is added to the end of the array.
425 
426  The object being added has its reference count increased, and if it's replacing
427  another object, then that one has its reference count decreased, and may be deleted.
428 
429  @param indexToChange the index whose value you want to change
430  @param newObject the new value to set for this index.
431  @see add, insert, remove
432  */
433  void set (int indexToChange, ObjectClass* newObject)
434  {
435  if (indexToChange >= 0)
436  {
437  const ScopedLockType lock (getLock());
438 
439  if (newObject != nullptr)
440  newObject->incReferenceCount();
441 
442  if (indexToChange < values.size())
443  {
444  releaseObject (values[indexToChange]);
445  values[indexToChange] = newObject;
446  }
447  else
448  {
449  values.add (newObject);
450  }
451  }
452  }
453 
454  /** Adds elements from another array to the end of this array.
455 
456  @param arrayToAddFrom the array from which to copy the elements
457  @param startIndex the first element of the other array to start copying from
458  @param numElementsToAdd how many elements to add from the other array. If this
459  value is negative or greater than the number of available elements,
460  all available elements will be copied.
461  @see add
462  */
463  void addArray (const ReferenceCountedArray& arrayToAddFrom,
464  int startIndex = 0,
465  int numElementsToAdd = -1) noexcept
466  {
467  const ScopedLockType lock1 (arrayToAddFrom.getLock());
468 
469  {
470  const ScopedLockType lock2 (getLock());
471 
472  auto numElementsAdded = values.addArray (arrayToAddFrom.values, startIndex, numElementsToAdd);
473  auto** e = values.end();
474 
475  for (int i = 0; i < numElementsAdded; ++i)
476  (*(--e))->incReferenceCount();
477  }
478  }
479 
480  /** Inserts a new object into the array assuming that the array is sorted.
481 
482  This will use a comparator to find the position at which the new object
483  should go. If the array isn't sorted, the behaviour of this
484  method will be unpredictable.
485 
486  @param comparator the comparator object to use to compare the elements - see the
487  sort() method for details about this object's form
488  @param newObject the new object to insert to the array
489  @returns the index at which the new object was added
490  @see add, sort
491  */
492  template <class ElementComparator>
493  int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
494  {
495  const ScopedLockType lock (getLock());
496  auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
497  insert (index, newObject);
498  return index;
499  }
500 
501  /** Inserts or replaces an object in the array, assuming it is sorted.
502 
503  This is similar to addSorted, but if a matching element already exists, then it will be
504  replaced by the new one, rather than the new one being added as well.
505  */
506  template <class ElementComparator>
507  void addOrReplaceSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
508  {
509  const ScopedLockType lock (getLock());
510  auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
511 
512  if (index > 0 && comparator.compareElements (newObject, values[index - 1]) == 0)
513  set (index - 1, newObject); // replace an existing object that matches
514  else
515  insert (index, newObject); // no match, so insert the new one
516  }
517 
518  /** Finds the index of an object in the array, assuming that the array is sorted.
519 
520  This will use a comparator to do a binary-chop to find the index of the given
521  element, if it exists. If the array isn't sorted, the behaviour of this
522  method will be unpredictable.
523 
524  @param comparator the comparator to use to compare the elements - see the sort()
525  method for details about the form this object should take
526  @param objectToLookFor the object to search for
527  @returns the index of the element, or -1 if it's not found
528  @see addSorted, sort
529  */
530  template <class ElementComparator>
531  int indexOfSorted (ElementComparator& comparator,
532  const ObjectClass* objectToLookFor) const noexcept
533  {
534  ignoreUnused (comparator);
535  const ScopedLockType lock (getLock());
536  int s = 0, e = values.size();
537 
538  while (s < e)
539  {
540  if (comparator.compareElements (objectToLookFor, values[s]) == 0)
541  return s;
542 
543  auto halfway = (s + e) / 2;
544 
545  if (halfway == s)
546  break;
547 
548  if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
549  s = halfway;
550  else
551  e = halfway;
552  }
553 
554  return -1;
555  }
556 
557  //==============================================================================
558  /** Removes an object from the array.
559 
560  This will remove the object at a given index and move back all the
561  subsequent objects to close the gap.
562 
563  If the index passed in is out-of-range, nothing will happen.
564 
565  The object that is removed will have its reference count decreased,
566  and may be deleted if not referenced from elsewhere.
567 
568  @param indexToRemove the index of the element to remove
569  @see removeObject, removeRange
570  */
571  void remove (int indexToRemove)
572  {
573  const ScopedLockType lock (getLock());
574 
575  if (isPositiveAndBelow (indexToRemove, values.size()))
576  {
577  auto** e = values.begin() + indexToRemove;
578  releaseObject (*e);
579  values.removeElements (indexToRemove, 1);
580 
581  if ((values.size() << 1) < values.capacity())
583  }
584  }
585 
586  /** Removes and returns an object from the array.
587 
588  This will remove the object at a given index and return it, moving back all
589  the subsequent objects to close the gap. If the index passed in is out-of-range,
590  nothing will happen and a null pointer will be returned.
591 
592  @param indexToRemove the index of the element to remove
593  @see remove, removeObject, removeRange
594  */
595  ObjectClassPtr removeAndReturn (int indexToRemove)
596  {
597  ObjectClassPtr removedItem;
598  const ScopedLockType lock (getLock());
599 
600  if (isPositiveAndBelow (indexToRemove, values.size()))
601  {
602  auto** e = values.begin() + indexToRemove;
603  removedItem = *e;
604  releaseObject (*e);
605  values.removeElements (indexToRemove, 1);
606 
607  if ((values.size() << 1) < values.capacity())
609  }
610 
611  return removedItem;
612  }
613 
614  /** Removes the first occurrence of a specified object from the array.
615 
616  If the item isn't found, no action is taken. If it is found, it is
617  removed and has its reference count decreased.
618 
619  @param objectToRemove the object to try to remove
620  @see remove, removeRange
621  */
622  void removeObject (ObjectClass* objectToRemove)
623  {
624  const ScopedLockType lock (getLock());
625  remove (indexOf (objectToRemove));
626  }
627 
628  /** Removes the first occurrence of a specified object from the array.
629 
630  If the item isn't found, no action is taken. If it is found, it is
631  removed and has its reference count decreased.
632 
633  @param objectToRemove the object to try to remove
634  @see remove, removeRange
635  */
636  void removeObject (const ObjectClassPtr& objectToRemove) { removeObject (objectToRemove.get()); }
637 
638  /** Removes a range of objects from the array.
639 
640  This will remove a set of objects, starting from the given index,
641  and move any subsequent elements down to close the gap.
642 
643  If the range extends beyond the bounds of the array, it will
644  be safely clipped to the size of the array.
645 
646  The objects that are removed will have their reference counts decreased,
647  and may be deleted if not referenced from elsewhere.
648 
649  @param startIndex the index of the first object to remove
650  @param numberToRemove how many objects should be removed
651  @see remove, removeObject
652  */
653  void removeRange (int startIndex,
654  int numberToRemove)
655  {
656  const ScopedLockType lock (getLock());
657  startIndex = jlimit (0, values.size(), startIndex);
658  auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
659  numberToRemove = endIndex - startIndex;
660 
661  if (numberToRemove > 0)
662  {
663  for (int i = startIndex; i < endIndex; ++i)
664  {
665  releaseObject (values[i]);
666  values[i] = nullptr; // (in case one of the destructors accesses this array and hits a dangling pointer)
667  }
668 
669  values.removeElements (startIndex, numberToRemove);
670 
671  if ((values.size() << 1) < values.capacity())
673  }
674  }
675 
676  /** Removes the last n objects from the array.
677 
678  The objects that are removed will have their reference counts decreased,
679  and may be deleted if not referenced from elsewhere.
680 
681  @param howManyToRemove how many objects to remove from the end of the array
682  @see remove, removeObject, removeRange
683  */
684  void removeLast (int howManyToRemove = 1)
685  {
686  const ScopedLockType lock (getLock());
687 
688  if (howManyToRemove > values.size())
689  howManyToRemove = values.size();
690 
691  while (--howManyToRemove >= 0)
692  remove (values.size() - 1);
693  }
694 
695  /** Swaps a pair of objects in the array.
696 
697  If either of the indexes passed in is out-of-range, nothing will happen,
698  otherwise the two objects at these positions will be exchanged.
699  */
700  void swap (int index1, int index2) noexcept
701  {
702  const ScopedLockType lock (getLock());
703 
704  if (isPositiveAndBelow (index1, values.size())
705  && isPositiveAndBelow (index2, values.size()))
706  {
707  std::swap (values[index1], values[index2]);
708  }
709  }
710 
711  /** Moves one of the objects to a different position.
712 
713  This will move the object to a specified index, shuffling along
714  any intervening elements as required.
715 
716  So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
717  move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
718 
719  @param currentIndex the index of the object to be moved. If this isn't a
720  valid index, then nothing will be done
721  @param newIndex the index at which you'd like this object to end up. If this
722  is less than zero, it will be moved to the end of the array
723  */
724  void move (int currentIndex, int newIndex) noexcept
725  {
726  if (currentIndex != newIndex)
727  {
728  const ScopedLockType lock (getLock());
729  values.move (currentIndex, newIndex);
730  }
731  }
732 
733  //==============================================================================
734  /** This swaps the contents of this array with those of another array.
735 
736  If you need to exchange two arrays, this is vastly quicker than using copy-by-value
737  because it just swaps their internal pointers.
738  */
739  template <class OtherArrayType>
740  void swapWith (OtherArrayType& otherArray) noexcept
741  {
742  const ScopedLockType lock1 (getLock());
743  const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
744  values.swapWith (otherArray.values);
745  }
746 
747  //==============================================================================
748  /** Compares this array to another one.
749 
750  @returns true only if the other array contains the same objects in the same order
751  */
752  bool operator== (const ReferenceCountedArray& other) const noexcept
753  {
754  const ScopedLockType lock2 (other.getLock());
755  const ScopedLockType lock1 (getLock());
756  return values == other.values;
757  }
758 
759  /** Compares this array to another one.
760 
761  @see operator==
762  */
764  {
765  return ! operator== (other);
766  }
767 
768  //==============================================================================
769  /** Sorts the elements in the array.
770 
771  This will use a comparator object to sort the elements into order. The object
772  passed must have a method of the form:
773  @code
774  int compareElements (ElementType first, ElementType second);
775  @endcode
776 
777  ..and this method must return:
778  - a value of < 0 if the first comes before the second
779  - a value of 0 if the two objects are equivalent
780  - a value of > 0 if the second comes before the first
781 
782  To improve performance, the compareElements() method can be declared as static or const.
783 
784  @param comparator the comparator to use for comparing elements.
785  @param retainOrderOfEquivalentItems if this is true, then items
786  which the comparator says are equivalent will be
787  kept in the order in which they currently appear
788  in the array. This is slower to perform, but may
789  be important in some cases. If it's false, a faster
790  algorithm is used, but equivalent elements may be
791  rearranged.
792 
793  @see sortArray
794  */
795  template <class ElementComparator>
796  void sort (ElementComparator& comparator,
797  bool retainOrderOfEquivalentItems = false) const noexcept
798  {
799  // If you pass in an object with a static compareElements() method, this
800  // avoids getting warning messages about the parameter being unused
801  ignoreUnused (comparator);
802 
803  const ScopedLockType lock (getLock());
804  sortArray (comparator, values.begin(), 0, values.size() - 1, retainOrderOfEquivalentItems);
805  }
806 
807  //==============================================================================
808  /** Reduces the amount of storage being used by the array.
809 
810  Arrays typically allocate slightly more storage than they need, and after
811  removing elements, they may have quite a lot of unused space allocated.
812  This method will reduce the amount of allocated storage to a minimum.
813  */
814  void minimiseStorageOverheads() noexcept
815  {
816  const ScopedLockType lock (getLock());
817  values.shrinkToNoMoreThan (values.size());
818  }
819 
820  /** Increases the array's internal storage to hold a minimum number of elements.
821 
822  Calling this before adding a large known number of elements means that
823  the array won't have to keep dynamically resizing itself as the elements
824  are added, and it'll therefore be more efficient.
825  */
826  void ensureStorageAllocated (const int minNumElements)
827  {
828  const ScopedLockType lock (getLock());
829  values.ensureAllocatedSize (minNumElements);
830  }
831 
832  //==============================================================================
833  /** Returns the CriticalSection that locks this array.
834  To lock, you can call getLock().enter() and getLock().exit(), or preferably use
835  an object of ScopedLockType as an RAII lock for it.
836  */
837  inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
838 
839  /** Returns the type of scoped lock to use for locking this array */
840  using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
841 
842  //==============================================================================
843  #ifndef DOXYGEN
844  // Note that the swapWithArray method has been replaced by a more flexible templated version,
845  // and renamed "swapWith" to be more consistent with the names used in other classes.
846  JUCE_DEPRECATED_WITH_BODY (void swapWithArray (ReferenceCountedArray& other) noexcept, { swapWith (other); })
847  #endif
848 
849 private:
850  //==============================================================================
852 
853  void releaseAllObjects()
854  {
855  for (auto& v : values)
856  releaseObject (v);
857 
858  values.clear();
859  }
860 
861  static void releaseObject (ObjectClass* o)
862  {
863  if (o != nullptr && o->decReferenceCountWithoutDeleting())
865  }
866 };
867 
868 } // namespace juce
869 
870 /** @}*/
const TypeOfCriticalSectionToUse & getLock() const noexcept
Returns the CriticalSection that locks this 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 swap(int index1, int index2) noexcept
Swaps a pair of objects in the array.
ObjectClassPtr removeAndReturn(int indexToRemove)
Removes and returns an object from the array.
ObjectClass ** data() const noexcept
Returns a pointer to the first element in the array.
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Inserts a new object into the array assuming that the array is sorted.
ObjectClass * add(ObjectClass *newObject)
Appends a new object to the end of the array.
void removeObject(ObjectClass *objectToRemove)
Removes the first occurrence of a specified object from the array.
ReferenceCountedArray()=default
Creates an empty array.
void addOrReplaceSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Inserts or replaces an object in the array, assuming it is sorted.
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&#39;t already contain it...
ObjectClassPtr operator[](int index) const noexcept
Returns a pointer to the object at this index in the 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 * insert(int indexToInsertAt, ObjectClass *newObject)
Inserts a new object into the array at the given index.
bool addIfNotAlreadyThere(ObjectClass *newObject)
Appends a new object at the end of the array as long as the array doesn&#39;t already contain it...
ReferenceCountedArray(const ReferenceCountedArray< OtherObjectClass, OtherCriticalSection > &other) noexcept
Creates a copy of another array.
int indexOf(const ObjectClass *objectToLookFor) const noexcept
Finds the index of the first occurrence of an object in the array.
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) const noexcept
Sorts the elements in the array.
ObjectClassPtr getLast() const noexcept
Returns a pointer to the last object in the array.
ObjectClassPtr getFirst() const noexcept
Returns a pointer to the first object in the array.
bool operator==(const ReferenceCountedArray &other) const noexcept
Compares this array to another one.
void ensureStorageAllocated(const int minNumElements)
Increases the array&#39;s internal storage to hold a minimum number of elements.
bool contains(const ObjectClass *objectToLookFor) const noexcept
Returns true if the array contains a specified object.
void minimiseStorageOverheads() noexcept
Reduces the amount of storage being used by the array.
ReferenceCountedArray(ReferenceCountedArray &&other) noexcept
Moves from another array.
ObjectClass * insert(int indexToInsertAt, const ObjectClassPtr &newObject)
Inserts a new object into the array at the given index.
int size() const noexcept
Returns the current number of objects in the array.
typename DummyCriticalSection ::ScopedLockType ScopedLockType
Returns the type of scoped lock to use for locking this array.
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
void clear()
Removes all objects from the array.
ObjectClass * getObjectPointer(int index) const noexcept
Returns a raw pointer to the object at this index in the array.
void clearQuick()
Removes all objects from the array without freeing the array&#39;s allocated storage. ...
ObjectClass * add(const ObjectClassPtr &newObject)
Appends a new object to the end of the array.
ReferenceCountedArray & operator=(const ReferenceCountedArray &other) noexcept
Copies another array into this one.
ReferencedType * get() const noexcept
Returns the object that this pointer references.
Used by container classes as an indirect way to delete an object of a particular type.
void addArray(const ReferenceCountedArray &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1) noexcept
Adds elements from another array to the end of this array.
void removeRange(int startIndex, int numberToRemove)
Removes a range of objects from the array.
A smart-pointer class which points to a reference-counted object.
bool contains(const ObjectClassPtr &objectToLookFor) const noexcept
Returns true if the array contains a specified object.
bool operator!=(const ReferenceCountedArray< ObjectClass, TypeOfCriticalSectionToUse > &other) const noexcept
Compares this array to another one.
int indexOf(const ObjectClassPtr &objectToLookFor) const noexcept
Finds the index of the first occurrence of an object in the array.
ObjectClass ** getRawDataPointer() const noexcept
Returns a pointer to the actual array data.
ObjectClass ** begin() const noexcept
Returns a pointer to the first element in the array.
void removeLast(int howManyToRemove=1)
Removes the last n objects from the array.
void removeObject(const ObjectClassPtr &objectToRemove)
Removes the first occurrence of a specified object from the array.
int indexOfSorted(ElementComparator &comparator, const ObjectClass *objectToLookFor) const noexcept
Finds the index of an object in the array, assuming that the array is sorted.
ObjectClass ** end() const noexcept
Returns a pointer to the element which follows the last element in the array.
Holds a list of objects derived from ReferenceCountedObject, or which implement basic reference-count...
ReferenceCountedArray(const ReferenceCountedArray &other) noexcept
Creates a copy of another array.
void move(int currentIndex, int newIndex) noexcept
Moves one of the objects to a different position.