| @@ -64,19 +64,15 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates an empty set. */ | /** Creates an empty set. */ | ||||
| SortedSet() noexcept | SortedSet() noexcept | ||||
| : numUsed (0) | |||||
| { | { | ||||
| } | } | ||||
| /** Creates a copy of another set. | /** Creates a copy of another set. | ||||
| @param other the set to copy | @param other the set to copy | ||||
| */ | */ | ||||
| SortedSet (const SortedSet& other) noexcept | |||||
| SortedSet (const SortedSet& other) | |||||
| : data (other.data) | |||||
| { | { | ||||
| const ScopedLockType lock (other.getLock()); | |||||
| numUsed = other.numUsed; | |||||
| data.setAllocatedSize (other.numUsed); | |||||
| memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); | |||||
| } | } | ||||
| /** Destructor. */ | /** Destructor. */ | ||||
| @@ -89,47 +85,22 @@ public: | |||||
| */ | */ | ||||
| SortedSet& operator= (const SortedSet& other) noexcept | SortedSet& operator= (const SortedSet& other) noexcept | ||||
| { | { | ||||
| if (this != &other) | |||||
| { | |||||
| const ScopedLockType lock1 (other.getLock()); | |||||
| const ScopedLockType lock2 (getLock()); | |||||
| data.ensureAllocatedSize (other.size()); | |||||
| numUsed = other.numUsed; | |||||
| memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); | |||||
| minimiseStorageOverheads(); | |||||
| } | |||||
| data = other.data; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Compares this set to another one. | /** Compares this set to another one. | ||||
| Two sets are considered equal if they both contain the same set of | |||||
| elements. | |||||
| Two sets are considered equal if they both contain the same set of elements. | |||||
| @param other the other set to compare with | @param other the other set to compare with | ||||
| */ | */ | ||||
| bool operator== (const SortedSet<ElementType>& other) const noexcept | bool operator== (const SortedSet<ElementType>& other) const noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| if (numUsed != other.numUsed) | |||||
| return false; | |||||
| for (int i = numUsed; --i >= 0;) | |||||
| if (! (data.elements[i] == other.data.elements[i])) | |||||
| return false; | |||||
| return true; | |||||
| return data == other.data; | |||||
| } | } | ||||
| /** Compares this set to another one. | /** Compares this set to another one. | ||||
| Two sets are considered equal if they both contain the same set of | |||||
| elements. | |||||
| Two sets are considered equal if they both contain the same set of elements. | |||||
| @param other the other set to compare with | @param other the other set to compare with | ||||
| */ | */ | ||||
| bool operator!= (const SortedSet<ElementType>& other) const noexcept | bool operator!= (const SortedSet<ElementType>& other) const noexcept | ||||
| @@ -148,9 +119,7 @@ public: | |||||
| */ | */ | ||||
| void clear() noexcept | void clear() noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| data.setAllocatedSize (0); | |||||
| numUsed = 0; | |||||
| data.clear(); | |||||
| } | } | ||||
| /** Removes all elements from the set without freeing the array's allocated storage. | /** Removes all elements from the set without freeing the array's allocated storage. | ||||
| @@ -159,8 +128,7 @@ public: | |||||
| */ | */ | ||||
| void clearQuick() noexcept | void clearQuick() noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| numUsed = 0; | |||||
| data.clearQuick(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -168,7 +136,7 @@ public: | |||||
| */ | */ | ||||
| inline int size() const noexcept | inline int size() const noexcept | ||||
| { | { | ||||
| return numUsed; | |||||
| return data.size(); | |||||
| } | } | ||||
| /** Returns one of the elements in the set. | /** Returns one of the elements in the set. | ||||
| @@ -184,9 +152,7 @@ public: | |||||
| */ | */ | ||||
| inline ElementType operator[] (const int index) const noexcept | inline ElementType operator[] (const int index) const noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| return isPositiveAndBelow (index, numUsed) ? data.elements [index] | |||||
| : ElementType(); | |||||
| return data [index]; | |||||
| } | } | ||||
| /** Returns one of the elements in the set, without checking the index passed in. | /** Returns one of the elements in the set, without checking the index passed in. | ||||
| @@ -199,9 +165,7 @@ public: | |||||
| */ | */ | ||||
| inline ElementType getUnchecked (const int index) const noexcept | inline ElementType getUnchecked (const int index) const noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| jassert (isPositiveAndBelow (index, numUsed)); | |||||
| return data.elements [index]; | |||||
| return data.getUnchecked (index); | |||||
| } | } | ||||
| /** Returns a direct reference to one of the elements in the set, without checking the index passed in. | /** Returns a direct reference to one of the elements in the set, without checking the index passed in. | ||||
| @@ -214,9 +178,7 @@ public: | |||||
| */ | */ | ||||
| inline ElementType& getReference (const int index) const noexcept | inline ElementType& getReference (const int index) const noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| jassert (isPositiveAndBelow (index, numUsed)); | |||||
| return data.elements [index]; | |||||
| return data.getReference (index); | |||||
| } | } | ||||
| /** Returns the first element in the set, or 0 if the set is empty. | /** Returns the first element in the set, or 0 if the set is empty. | ||||
| @@ -225,8 +187,7 @@ public: | |||||
| */ | */ | ||||
| inline ElementType getFirst() const noexcept | inline ElementType getFirst() const noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| return numUsed > 0 ? data.elements [0] : ElementType(); | |||||
| return data.getFirst(); | |||||
| } | } | ||||
| /** Returns the last element in the set, or 0 if the set is empty. | /** Returns the last element in the set, or 0 if the set is empty. | ||||
| @@ -235,8 +196,7 @@ public: | |||||
| */ | */ | ||||
| inline ElementType getLast() const noexcept | inline ElementType getLast() const noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| return numUsed > 0 ? data.elements [numUsed - 1] : ElementType(); | |||||
| return data.getLast(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -245,7 +205,7 @@ public: | |||||
| */ | */ | ||||
| inline ElementType* begin() const noexcept | inline ElementType* begin() const noexcept | ||||
| { | { | ||||
| return data.elements; | |||||
| return data.begin(); | |||||
| } | } | ||||
| /** Returns a pointer to the element which follows the last element in the set. | /** Returns a pointer to the element which follows the last element in the set. | ||||
| @@ -253,7 +213,7 @@ public: | |||||
| */ | */ | ||||
| inline ElementType* end() const noexcept | inline ElementType* end() const noexcept | ||||
| { | { | ||||
| return data.elements + numUsed; | |||||
| return data.end(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -267,32 +227,27 @@ public: | |||||
| */ | */ | ||||
| int indexOf (const ElementType elementToLookFor) const noexcept | int indexOf (const ElementType elementToLookFor) const noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| const ScopedLockType lock (data.getLock()); | |||||
| int start = 0; | int start = 0; | ||||
| int end_ = numUsed; | |||||
| int end_ = data.size(); | |||||
| for (;;) | for (;;) | ||||
| { | { | ||||
| if (start >= end_) | if (start >= end_) | ||||
| { | |||||
| return -1; | return -1; | ||||
| } | |||||
| else if (elementToLookFor == data.elements [start]) | |||||
| { | |||||
| if (elementToLookFor == data.getReference (start)) | |||||
| return start; | return start; | ||||
| } | |||||
| else | |||||
| { | |||||
| const int halfway = (start + end_) >> 1; | |||||
| if (halfway == start) | |||||
| return -1; | |||||
| else if (elementToLookFor < data.elements [halfway]) | |||||
| end_ = halfway; | |||||
| else | |||||
| start = halfway; | |||||
| } | |||||
| const int halfway = (start + end_) >> 1; | |||||
| if (halfway == start) | |||||
| return -1; | |||||
| else if (elementToLookFor < data.getReference (halfway)) | |||||
| end_ = halfway; | |||||
| else | |||||
| start = halfway; | |||||
| } | } | ||||
| } | } | ||||
| @@ -306,29 +261,24 @@ public: | |||||
| const ScopedLockType lock (getLock()); | const ScopedLockType lock (getLock()); | ||||
| int start = 0; | int start = 0; | ||||
| int end_ = numUsed; | |||||
| int end_ = data.size(); | |||||
| for (;;) | for (;;) | ||||
| { | { | ||||
| if (start >= end_) | if (start >= end_) | ||||
| { | |||||
| return false; | return false; | ||||
| } | |||||
| else if (elementToLookFor == data.elements [start]) | |||||
| { | |||||
| if (elementToLookFor == data.getReference (start)) | |||||
| return true; | return true; | ||||
| } | |||||
| else | |||||
| { | |||||
| const int halfway = (start + end_) >> 1; | |||||
| if (halfway == start) | |||||
| return false; | |||||
| else if (elementToLookFor < data.elements [halfway]) | |||||
| end_ = halfway; | |||||
| else | |||||
| start = halfway; | |||||
| } | |||||
| const int halfway = (start + end_) >> 1; | |||||
| if (halfway == start) | |||||
| return false; | |||||
| else if (elementToLookFor < data.getReference (halfway)) | |||||
| end_ = halfway; | |||||
| else | |||||
| start = halfway; | |||||
| } | } | ||||
| } | } | ||||
| @@ -343,38 +293,35 @@ public: | |||||
| const ScopedLockType lock (getLock()); | const ScopedLockType lock (getLock()); | ||||
| int start = 0; | int start = 0; | ||||
| int end_ = numUsed; | |||||
| int end_ = data.size(); | |||||
| for (;;) | for (;;) | ||||
| { | { | ||||
| if (start >= end_) | if (start >= end_) | ||||
| { | { | ||||
| jassert (start <= end_); | jassert (start <= end_); | ||||
| insertInternal (start, newElement); | |||||
| data.insert (start, newElement); | |||||
| break; | break; | ||||
| } | } | ||||
| else if (newElement == data.elements [start]) | |||||
| { | |||||
| if (newElement == data.getReference (start)) | |||||
| break; | break; | ||||
| } | |||||
| else | |||||
| { | |||||
| const int halfway = (start + end_) >> 1; | |||||
| if (halfway == start) | |||||
| { | |||||
| if (newElement < data.elements [halfway]) | |||||
| insertInternal (start, newElement); | |||||
| else | |||||
| insertInternal (start + 1, newElement); | |||||
| const int halfway = (start + end_) >> 1; | |||||
| break; | |||||
| } | |||||
| else if (newElement < data.elements [halfway]) | |||||
| end_ = halfway; | |||||
| if (halfway == start) | |||||
| { | |||||
| if (newElement < data.getReference (halfway)) | |||||
| data.insert (start, newElement); | |||||
| else | else | ||||
| start = halfway; | |||||
| data.insert (start + 1, newElement); | |||||
| break; | |||||
| } | } | ||||
| else if (newElement < data.getReference (halfway)) | |||||
| end_ = halfway; | |||||
| else | |||||
| start = halfway; | |||||
| } | } | ||||
| } | } | ||||
| @@ -424,12 +371,12 @@ public: | |||||
| if (numElementsToAdd < 0 || startIndex + numElementsToAdd > setToAddFrom.size()) | if (numElementsToAdd < 0 || startIndex + numElementsToAdd > setToAddFrom.size()) | ||||
| numElementsToAdd = setToAddFrom.size() - startIndex; | numElementsToAdd = setToAddFrom.size() - startIndex; | ||||
| addArray (setToAddFrom.data.elements + startIndex, numElementsToAdd); | |||||
| if (numElementsToAdd > 0) | |||||
| addArray (&setToAddFrom.data.getReference (startIndex), numElementsToAdd); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Removes an element from the set. | /** Removes an element from the set. | ||||
| @@ -442,26 +389,7 @@ public: | |||||
| */ | */ | ||||
| ElementType remove (const int indexToRemove) noexcept | ElementType remove (const int indexToRemove) noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| if (isPositiveAndBelow (indexToRemove, numUsed)) | |||||
| { | |||||
| --numUsed; | |||||
| ElementType* const e = data.elements + indexToRemove; | |||||
| ElementType const removed = *e; | |||||
| const int numberToShift = numUsed - indexToRemove; | |||||
| if (numberToShift > 0) | |||||
| memmove (e, e + 1, sizeof (ElementType) * (size_t) numberToShift); | |||||
| if ((numUsed << 1) < data.numAllocated) | |||||
| minimiseStorageOverheads(); | |||||
| return removed; | |||||
| } | |||||
| return ElementType(); | |||||
| return data.remove (indexToRemove); | |||||
| } | } | ||||
| /** Removes an item from the set. | /** Removes an item from the set. | ||||
| @@ -474,7 +402,7 @@ public: | |||||
| void removeValue (const ElementType valueToRemove) noexcept | void removeValue (const ElementType valueToRemove) noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | const ScopedLockType lock (getLock()); | ||||
| remove (indexOf (valueToRemove)); | |||||
| data.remove (indexOf (valueToRemove)); | |||||
| } | } | ||||
| /** Removes any elements which are also in another set. | /** Removes any elements which are also in another set. | ||||
| @@ -492,14 +420,11 @@ public: | |||||
| { | { | ||||
| clear(); | clear(); | ||||
| } | } | ||||
| else | |||||
| else if (otherSet.size() > 0) | |||||
| { | { | ||||
| if (otherSet.size() > 0) | |||||
| { | |||||
| for (int i = numUsed; --i >= 0;) | |||||
| if (otherSet.contains (data.elements [i])) | |||||
| remove (i); | |||||
| } | |||||
| for (int i = data.size(); --i >= 0;) | |||||
| if (otherSet.contains (data.getReference (i))) | |||||
| remove (i); | |||||
| } | } | ||||
| } | } | ||||
| @@ -524,8 +449,8 @@ public: | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| for (int i = numUsed; --i >= 0;) | |||||
| if (! otherSet.contains (data.elements [i])) | |||||
| for (int i = data.size(); --i >= 0;) | |||||
| if (! otherSet.contains (data.getReference (i))) | |||||
| remove (i); | remove (i); | ||||
| } | } | ||||
| } | } | ||||
| @@ -538,11 +463,7 @@ public: | |||||
| */ | */ | ||||
| void swapWith (SortedSet& otherSet) noexcept | void swapWith (SortedSet& otherSet) noexcept | ||||
| { | { | ||||
| const ScopedLockType lock1 (getLock()); | |||||
| const ScopedLockType lock2 (otherSet.getLock()); | |||||
| data.swapWith (otherSet.data); | |||||
| swapVariables (numUsed, otherSet.numUsed); | |||||
| data.swapWithArray (otherSet.data); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -554,8 +475,7 @@ public: | |||||
| */ | */ | ||||
| void minimiseStorageOverheads() noexcept | void minimiseStorageOverheads() noexcept | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| data.shrinkToNoMoreThan (numUsed); | |||||
| data.minimiseStorageOverheads(); | |||||
| } | } | ||||
| /** Increases the set's internal storage to hold a minimum number of elements. | /** Increases the set's internal storage to hold a minimum number of elements. | ||||
| @@ -566,8 +486,7 @@ public: | |||||
| */ | */ | ||||
| void ensureStorageAllocated (const int minNumElements) | void ensureStorageAllocated (const int minNumElements) | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (minNumElements); | |||||
| data.ensureStorageAllocated (minNumElements); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -575,7 +494,7 @@ public: | |||||
| To lock, you can call getLock().enter() and getLock().exit(), or preferably use | To lock, you can call getLock().enter() and getLock().exit(), or preferably use | ||||
| an object of ScopedLockType as an RAII lock for it. | an object of ScopedLockType as an RAII lock for it. | ||||
| */ | */ | ||||
| inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return data; } | |||||
| inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return data.getLock(); } | |||||
| /** Returns the type of scoped lock to use for locking this array */ | /** Returns the type of scoped lock to use for locking this array */ | ||||
| typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType; | typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType; | ||||
| @@ -583,22 +502,7 @@ public: | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| ArrayAllocationBase <ElementType, TypeOfCriticalSectionToUse> data; | |||||
| int numUsed; | |||||
| void insertInternal (const int indexToInsertAt, const ElementType newElement) noexcept | |||||
| { | |||||
| data.ensureAllocatedSize (numUsed + 1); | |||||
| ElementType* const insertPos = data.elements + indexToInsertAt; | |||||
| const int numberToMove = numUsed - indexToInsertAt; | |||||
| if (numberToMove > 0) | |||||
| memmove (insertPos + 1, insertPos, sizeof (ElementType) * (size_t) numberToMove); | |||||
| new (insertPos) ElementType (newElement); | |||||
| ++numUsed; | |||||
| } | |||||
| Array <ElementType, TypeOfCriticalSectionToUse> data; | |||||
| }; | }; | ||||
| #if JUCE_MSVC | #if JUCE_MSVC | ||||