OpenShot Library | OpenShotAudio  0.2.1
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() 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  */
853  void minimiseStorageOverheads() noexcept
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 
888 private:
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())
908  }
909 };
910 
911 } // namespace juce
912 
913 /** @}*/
ObjectClass ** end() noexcept
Returns a pointer to the element which follows the last element in the array.
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.
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition: juce_Array.h:587
ObjectClass *const * begin() const noexcept
Returns a pointer to the first element in the array.
ObjectClassPtr removeAndReturn(int indexToRemove)
Removes and returns an object from the array.
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Inserts a new object into the array assuming that the array is sorted.
ObjectClass ** begin() noexcept
Returns a pointer to the first element in the array.
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.
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.
ObjectClass *const * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
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.
ObjectClass *const * data() const noexcept
Returns a pointer to the first element in the 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.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
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.
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.
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.
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) noexcept
Sorts the elements in the array.
ObjectClass ** data() noexcept
Returns a pointer to the first element in the array.