openshot-audio  0.1.4
juce_ReferenceCountedArray.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the juce_core module of the JUCE library.
5  Copyright (c) 2015 - ROLI Ltd.
6 
7  Permission to use, copy, modify, and/or distribute this software for any purpose with
8  or without fee is hereby granted, provided that the above copyright notice and this
9  permission notice appear in all copies.
10 
11  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
12  TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
13  NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
15  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18  ------------------------------------------------------------------------------
19 
20  NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
21  All other JUCE modules are covered by a dual GPL/commercial license, so if you are
22  using any other modules, be sure to check that you also comply with their license.
23 
24  For more details, visit www.juce.com
25 
26  ==============================================================================
27 */
28 
29 #ifndef JUCE_REFERENCECOUNTEDARRAY_H_INCLUDED
30 #define JUCE_REFERENCECOUNTEDARRAY_H_INCLUDED
31 
32 
33 //==============================================================================
54 template <class ObjectClass, class TypeOfCriticalSectionToUse = DummyCriticalSection>
56 {
57 public:
59 
60  //==============================================================================
65  : numUsed (0)
66  {
67  }
68 
71  {
72  const ScopedLockType lock (other.getLock());
73  numUsed = other.size();
74  data.setAllocatedSize (numUsed);
75  memcpy (data.elements, other.getRawDataPointer(), (size_t) numUsed * sizeof (ObjectClass*));
76 
77  for (int i = numUsed; --i >= 0;)
78  if (ObjectClass* o = data.elements[i])
79  o->incReferenceCount();
80  }
81 
83  template <class OtherObjectClass, class OtherCriticalSection>
85  {
87  numUsed = other.size();
88  data.setAllocatedSize (numUsed);
89  memcpy (data.elements, other.getRawDataPointer(), numUsed * sizeof (ObjectClass*));
90 
91  for (int i = numUsed; --i >= 0;)
92  if (ObjectClass* o = data.elements[i])
93  o->incReferenceCount();
94  }
95 
100  {
101  ReferenceCountedArray otherCopy (other);
102  swapWith (otherCopy);
103  return *this;
104  }
105 
109  template <class OtherObjectClass>
111  {
113  swapWith (otherCopy);
114  return *this;
115  }
116 
121  {
123  }
124 
125  //==============================================================================
129  void clear()
130  {
131  const ScopedLockType lock (getLock());
133  data.setAllocatedSize (0);
134  }
135 
140  void clearQuick()
141  {
142  const ScopedLockType lock (getLock());
144  }
145 
147  inline int size() const noexcept
148  {
149  return numUsed;
150  }
151 
160  inline ObjectClassPtr operator[] (const int index) const noexcept
161  {
162  return getObjectPointer (index);
163  }
164 
171  inline ObjectClassPtr getUnchecked (const int index) const noexcept
172  {
173  return getObjectPointerUnchecked (index);
174  }
175 
184  inline ObjectClass* getObjectPointer (const int index) const noexcept
185  {
186  const ScopedLockType lock (getLock());
187 
188  if (isPositiveAndBelow (index, numUsed))
189  {
190  jassert (data.elements != nullptr);
191  return data.elements [index];
192  }
193 
194  return ObjectClassPtr();
195  }
196 
200  inline ObjectClass* getObjectPointerUnchecked (const int index) const noexcept
201  {
202  const ScopedLockType lock (getLock());
203  jassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
204  return data.elements [index];
205  }
206 
212  inline ObjectClassPtr getFirst() const noexcept
213  {
214  const ScopedLockType lock (getLock());
215 
216  if (numUsed > 0)
217  {
218  jassert (data.elements != nullptr);
219  return data.elements [0];
220  }
221 
222  return ObjectClassPtr();
223  }
224 
230  inline ObjectClassPtr getLast() const noexcept
231  {
232  const ScopedLockType lock (getLock());
233 
234  if (numUsed > 0)
235  {
236  jassert (data.elements != nullptr);
237  return data.elements [numUsed - 1];
238  }
239 
240  return ObjectClassPtr();
241  }
242 
247  inline ObjectClass** getRawDataPointer() const noexcept
248  {
249  return data.elements;
250  }
251 
252  //==============================================================================
256  inline ObjectClass** begin() const noexcept
257  {
258  return data.elements;
259  }
260 
264  inline ObjectClass** end() const noexcept
265  {
266  return data.elements + numUsed;
267  }
268 
269  //==============================================================================
275  int indexOf (const ObjectClass* const objectToLookFor) const noexcept
276  {
277  const ScopedLockType lock (getLock());
278  ObjectClass** e = data.elements.getData();
279  ObjectClass** const endPointer = e + numUsed;
280 
281  while (e != endPointer)
282  {
283  if (objectToLookFor == *e)
284  return static_cast <int> (e - data.elements.getData());
285 
286  ++e;
287  }
288 
289  return -1;
290  }
291 
297  bool contains (const ObjectClass* const objectToLookFor) const noexcept
298  {
299  const ScopedLockType lock (getLock());
300  ObjectClass** e = data.elements.getData();
301  ObjectClass** const endPointer = e + numUsed;
302 
303  while (e != endPointer)
304  {
305  if (objectToLookFor == *e)
306  return true;
307 
308  ++e;
309  }
310 
311  return false;
312  }
313 
321  ObjectClass* add (ObjectClass* const newObject) noexcept
322  {
323  const ScopedLockType lock (getLock());
324  data.ensureAllocatedSize (numUsed + 1);
325  jassert (data.elements != nullptr);
326  data.elements [numUsed++] = newObject;
327 
328  if (newObject != nullptr)
329  newObject->incReferenceCount();
330 
331  return newObject;
332  }
333 
347  ObjectClass* insert (int indexToInsertAt,
348  ObjectClass* const newObject) noexcept
349  {
350  if (indexToInsertAt < 0)
351  return add (newObject);
352 
353  const ScopedLockType lock (getLock());
354 
355  if (indexToInsertAt > numUsed)
356  indexToInsertAt = numUsed;
357 
358  data.ensureAllocatedSize (numUsed + 1);
359  jassert (data.elements != nullptr);
360 
361  ObjectClass** const e = data.elements + indexToInsertAt;
362  const int numToMove = numUsed - indexToInsertAt;
363 
364  if (numToMove > 0)
365  memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove);
366 
367  *e = newObject;
368 
369  if (newObject != nullptr)
370  newObject->incReferenceCount();
371 
372  ++numUsed;
373 
374  return newObject;
375  }
376 
384  void addIfNotAlreadyThere (ObjectClass* const newObject) noexcept
385  {
386  const ScopedLockType lock (getLock());
387  if (! contains (newObject))
388  add (newObject);
389  }
390 
403  void set (const int indexToChange,
404  ObjectClass* const newObject)
405  {
406  if (indexToChange >= 0)
407  {
408  const ScopedLockType lock (getLock());
409 
410  if (newObject != nullptr)
411  newObject->incReferenceCount();
412 
413  if (indexToChange < numUsed)
414  {
415  if (ObjectClass* o = data.elements [indexToChange])
416  releaseObject (o);
417 
418  data.elements [indexToChange] = newObject;
419  }
420  else
421  {
422  data.ensureAllocatedSize (numUsed + 1);
423  jassert (data.elements != nullptr);
424  data.elements [numUsed++] = newObject;
425  }
426  }
427  }
428 
439  int startIndex = 0,
440  int numElementsToAdd = -1) noexcept
441  {
442  const ScopedLockType lock1 (arrayToAddFrom.getLock());
443 
444  {
445  const ScopedLockType lock2 (getLock());
446 
447  if (startIndex < 0)
448  {
449  jassertfalse;
450  startIndex = 0;
451  }
452 
453  if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
454  numElementsToAdd = arrayToAddFrom.size() - startIndex;
455 
456  if (numElementsToAdd > 0)
457  {
458  data.ensureAllocatedSize (numUsed + numElementsToAdd);
459 
460  while (--numElementsToAdd >= 0)
461  add (arrayToAddFrom.getUnchecked (startIndex++));
462  }
463  }
464  }
465 
478  template <class ElementComparator>
479  int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
480  {
481  const ScopedLockType lock (getLock());
482  const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newObject, 0, numUsed);
483  insert (index, newObject);
484  return index;
485  }
486 
492  template <class ElementComparator>
493  void addOrReplaceSorted (ElementComparator& comparator,
494  ObjectClass* newObject) noexcept
495  {
496  const ScopedLockType lock (getLock());
497  const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newObject, 0, numUsed);
498 
499  if (index > 0 && comparator.compareElements (newObject, data.elements [index - 1]) == 0)
500  set (index - 1, newObject); // replace an existing object that matches
501  else
502  insert (index, newObject); // no match, so insert the new one
503  }
504 
517  template <class ElementComparator>
518  int indexOfSorted (ElementComparator& comparator,
519  const ObjectClass* const objectToLookFor) const noexcept
520  {
521  (void) comparator;
522  const ScopedLockType lock (getLock());
523  int s = 0, e = numUsed;
524 
525  while (s < e)
526  {
527  if (comparator.compareElements (objectToLookFor, data.elements [s]) == 0)
528  return s;
529 
530  const int halfway = (s + e) / 2;
531  if (halfway == s)
532  break;
533 
534  if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0)
535  s = halfway;
536  else
537  e = halfway;
538  }
539 
540  return -1;
541  }
542 
543  //==============================================================================
557  void remove (const int indexToRemove)
558  {
559  const ScopedLockType lock (getLock());
560 
561  if (isPositiveAndBelow (indexToRemove, numUsed))
562  {
563  ObjectClass** const e = data.elements + indexToRemove;
564 
565  if (ObjectClass* o = *e)
566  releaseObject (o);
567 
568  --numUsed;
569  const int numberToShift = numUsed - indexToRemove;
570 
571  if (numberToShift > 0)
572  memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numberToShift);
573 
574  if ((numUsed << 1) < data.numAllocated)
576  }
577  }
578 
588  ObjectClassPtr removeAndReturn (const int indexToRemove)
589  {
590  ObjectClassPtr removedItem;
591  const ScopedLockType lock (getLock());
592 
593  if (isPositiveAndBelow (indexToRemove, numUsed))
594  {
595  ObjectClass** const e = data.elements + indexToRemove;
596 
597  if (ObjectClass* o = *e)
598  {
599  removedItem = o;
600  releaseObject (o);
601  }
602 
603  --numUsed;
604  const int numberToShift = numUsed - indexToRemove;
605 
606  if (numberToShift > 0)
607  memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numberToShift);
608 
609  if ((numUsed << 1) < data.numAllocated)
611  }
612 
613  return removedItem;
614  }
615 
624  void removeObject (ObjectClass* const objectToRemove)
625  {
626  const ScopedLockType lock (getLock());
627  remove (indexOf (objectToRemove));
628  }
629 
645  void removeRange (const int startIndex,
646  const int numberToRemove)
647  {
648  const ScopedLockType lock (getLock());
649 
650  const int start = jlimit (0, numUsed, startIndex);
651  const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
652 
653  if (endIndex > start)
654  {
655  int i;
656  for (i = start; i < endIndex; ++i)
657  {
658  if (ObjectClass* o = data.elements[i])
659  {
660  releaseObject (o);
661  data.elements[i] = nullptr; // (in case one of the destructors accesses this array and hits a dangling pointer)
662  }
663  }
664 
665  const int rangeSize = endIndex - start;
666  ObjectClass** e = data.elements + start;
667  i = numUsed - endIndex;
668  numUsed -= rangeSize;
669 
670  while (--i >= 0)
671  {
672  *e = e [rangeSize];
673  ++e;
674  }
675 
676  if ((numUsed << 1) < data.numAllocated)
678  }
679  }
680 
689  void removeLast (int howManyToRemove = 1)
690  {
691  const ScopedLockType lock (getLock());
692 
693  if (howManyToRemove > numUsed)
694  howManyToRemove = numUsed;
695 
696  while (--howManyToRemove >= 0)
697  remove (numUsed - 1);
698  }
699 
705  void swap (const int index1,
706  const int index2) noexcept
707  {
708  const ScopedLockType lock (getLock());
709 
710  if (isPositiveAndBelow (index1, numUsed)
711  && isPositiveAndBelow (index2, numUsed))
712  {
713  std::swap (data.elements [index1],
714  data.elements [index2]);
715  }
716  }
717 
731  void move (const int currentIndex,
732  int newIndex) noexcept
733  {
734  if (currentIndex != newIndex)
735  {
736  const ScopedLockType lock (getLock());
737 
738  if (isPositiveAndBelow (currentIndex, numUsed))
739  {
740  if (! isPositiveAndBelow (newIndex, numUsed))
741  newIndex = numUsed - 1;
742 
743  ObjectClass* const value = data.elements [currentIndex];
744 
745  if (newIndex > currentIndex)
746  {
747  memmove (data.elements + currentIndex,
748  data.elements + currentIndex + 1,
749  sizeof (ObjectClass*) * (size_t) (newIndex - currentIndex));
750  }
751  else
752  {
753  memmove (data.elements + newIndex + 1,
754  data.elements + newIndex,
755  sizeof (ObjectClass*) * (size_t) (currentIndex - newIndex));
756  }
757 
758  data.elements [newIndex] = value;
759  }
760  }
761  }
762 
763  //==============================================================================
769  template <class OtherArrayType>
770  void swapWith (OtherArrayType& otherArray) noexcept
771  {
772  const ScopedLockType lock1 (getLock());
773  const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
774  data.swapWith (otherArray.data);
775  std::swap (numUsed, otherArray.numUsed);
776  }
777 
778  //==============================================================================
783  bool operator== (const ReferenceCountedArray& other) const noexcept
784  {
785  const ScopedLockType lock2 (other.getLock());
786  const ScopedLockType lock1 (getLock());
787 
788  if (numUsed != other.numUsed)
789  return false;
790 
791  for (int i = numUsed; --i >= 0;)
792  if (data.elements [i] != other.data.elements [i])
793  return false;
794 
795  return true;
796  }
797 
803  {
804  return ! operator== (other);
805  }
806 
807  //==============================================================================
834  template <class ElementComparator>
835  void sort (ElementComparator& comparator,
836  const bool retainOrderOfEquivalentItems = false) const noexcept
837  {
838  (void) comparator; // if you pass in an object with a static compareElements() method, this
839  // avoids getting warning messages about the parameter being unused
840 
841  const ScopedLockType lock (getLock());
842  sortArray (comparator, data.elements.getData(), 0, size() - 1, retainOrderOfEquivalentItems);
843  }
844 
845  //==============================================================================
853  {
854  const ScopedLockType lock (getLock());
855  data.shrinkToNoMoreThan (numUsed);
856  }
857 
864  void ensureStorageAllocated (const int minNumElements)
865  {
866  const ScopedLockType lock (getLock());
867  data.ensureAllocatedSize (minNumElements);
868  }
869 
870  //==============================================================================
875  inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return data; }
876 
878  typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
879 
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  int numUsed;
892 
894  {
895  while (numUsed > 0)
896  if (ObjectClass* o = data.elements [--numUsed])
897  releaseObject (o);
898 
899  jassert (numUsed == 0);
900  }
901 
902  static void releaseObject (ObjectClass* o)
903  {
904  if (o->decReferenceCountWithoutDeleting())
906  }
907 };
908 
909 
910 #endif // JUCE_REFERENCECOUNTEDARRAY_H_INCLUDED
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Definition: juce_ReferenceCountedArray.h:479
void swapWith(OtherArrayType &otherArray) noexcept
Definition: juce_ReferenceCountedArray.h:770
ReferenceCountedArray & operator=(const ReferenceCountedArray &other) noexcept
Definition: juce_ReferenceCountedArray.h:99
ReferenceCountedArray() noexcept
Definition: juce_ReferenceCountedArray.h:64
void releaseAllObjects()
Definition: juce_ReferenceCountedArray.h:893
#define noexcept
Definition: juce_CompilerSupport.h:141
ObjectClass ** end() const noexcept
Definition: juce_ReferenceCountedArray.h:264
void clearQuick()
Definition: juce_ReferenceCountedArray.h:140
ObjectClass ** begin() const noexcept
Definition: juce_ReferenceCountedArray.h:256
bool isPositiveAndBelow(Type valueToTest, Type upperLimit) noexcept
Definition: juce_core.h:238
Definition: juce_ArrayAllocationBase.h:46
ObjectClassPtr getUnchecked(const int index) const noexcept
Definition: juce_ReferenceCountedArray.h:171
void sort(ElementComparator &comparator, const bool retainOrderOfEquivalentItems=false) const noexcept
Definition: juce_ReferenceCountedArray.h:835
bool operator!=(const ReferenceCountedArray< ObjectClass, TypeOfCriticalSectionToUse > &other) const noexcept
Definition: juce_ReferenceCountedArray.h:802
void addIfNotAlreadyThere(ObjectClass *const newObject) noexcept
Definition: juce_ReferenceCountedArray.h:384
int size() const noexcept
Definition: juce_ReferenceCountedArray.h:147
#define jassertfalse
Definition: juce_PlatformDefs.h:141
int indexOfSorted(ElementComparator &comparator, const ObjectClass *const objectToLookFor) const noexcept
Definition: juce_ReferenceCountedArray.h:518
~ReferenceCountedArray()
Definition: juce_ReferenceCountedArray.h:120
ObjectClass * insert(int indexToInsertAt, ObjectClass *const newObject) noexcept
Definition: juce_ReferenceCountedArray.h:347
void removeLast(int howManyToRemove=1)
Definition: juce_ReferenceCountedArray.h:689
ObjectClassPtr getLast() const noexcept
Definition: juce_ReferenceCountedArray.h:230
DummyCriticalSection ::ScopedLockType ScopedLockType
Definition: juce_ReferenceCountedArray.h:878
Definition: juce_ReferenceCountedArray.h:55
static void releaseObject(ObjectClass *o)
Definition: juce_ReferenceCountedArray.h:902
void removeRange(const int startIndex, const int numberToRemove)
Definition: juce_ReferenceCountedArray.h:645
void addArray(const ReferenceCountedArray< ObjectClass, TypeOfCriticalSectionToUse > &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1) noexcept
Definition: juce_ReferenceCountedArray.h:438
ReferenceCountedObjectPtr< ObjectClass > ObjectClassPtr
Definition: juce_ReferenceCountedArray.h:58
void clear()
Definition: juce_ReferenceCountedArray.h:129
Definition: juce_ReferenceCountedObject.h:227
const TypeOfCriticalSectionToUse & getLock() const noexcept
Definition: juce_ReferenceCountedArray.h:875
bool operator==(const ReferenceCountedArray &other) const noexcept
Definition: juce_ReferenceCountedArray.h:783
void ensureStorageAllocated(const int minNumElements)
Definition: juce_ReferenceCountedArray.h:864
void minimiseStorageOverheads() noexcept
Definition: juce_ReferenceCountedArray.h:852
ObjectClassPtr getFirst() const noexcept
Definition: juce_ReferenceCountedArray.h:212
Definition: juce_ContainerDeletePolicy.h:44
Type jlimit(const Type lowerLimit, const Type upperLimit, const Type valueToConstrain) noexcept
Definition: juce_MathsFunctions.h:220
JUCE_DEPRECATED_WITH_BODY(void swapWithArray(ReferenceCountedArray &other) noexcept, { swapWith(other);}) private int numUsed
Definition: juce_ReferenceCountedArray.h:885
ObjectClass ** getRawDataPointer() const noexcept
Definition: juce_ReferenceCountedArray.h:247
ObjectClass * getObjectPointer(const int index) const noexcept
Definition: juce_ReferenceCountedArray.h:184
ObjectClassPtr operator[](const int index) const noexcept
Definition: juce_ReferenceCountedArray.h:160
void swap(const int index1, const int index2) noexcept
Definition: juce_ReferenceCountedArray.h:705
#define jassert(a)
Definition: juce_PlatformDefs.h:146
void addOrReplaceSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Definition: juce_ReferenceCountedArray.h:493
ObjectClassPtr removeAndReturn(const int indexToRemove)
Definition: juce_ReferenceCountedArray.h:588
ReferenceCountedArray(const ReferenceCountedArray< OtherObjectClass, OtherCriticalSection > &other) noexcept
Definition: juce_ReferenceCountedArray.h:84
ObjectClass * getObjectPointerUnchecked(const int index) const noexcept
Definition: juce_ReferenceCountedArray.h:200
void move(const int currentIndex, int newIndex) noexcept
Definition: juce_ReferenceCountedArray.h:731
#define JUCE_DEPRECATED_WITH_BODY(functionDef, body)
Definition: juce_PlatformDefs.h:320
bool contains(const ObjectClass *const objectToLookFor) const noexcept
Definition: juce_ReferenceCountedArray.h:297
ReferenceCountedArray(const ReferenceCountedArray &other) noexcept
Definition: juce_ReferenceCountedArray.h:70
ObjectClass * add(ObjectClass *const newObject) noexcept
Definition: juce_ReferenceCountedArray.h:321
int indexOf(const ObjectClass *const objectToLookFor) const noexcept
Definition: juce_ReferenceCountedArray.h:275
void removeObject(ObjectClass *const objectToRemove)
Definition: juce_ReferenceCountedArray.h:624