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