From 40929e5db92aa0ac979505a8aa47fa78fdbfbfbb Mon Sep 17 00:00:00 2001 From: jules Date: Mon, 21 May 2012 12:07:03 +0100 Subject: [PATCH] Tidied up ReadWriteLock a bit, and optimised Array to reduce allocation frequency when working with small numbers of items. --- modules/juce_core/containers/juce_Array.h | 51 +++++++---------- .../juce_core/threads/juce_ReadWriteLock.cpp | 57 ++++++++----------- .../juce_core/threads/juce_ReadWriteLock.h | 9 ++- 3 files changed, 54 insertions(+), 63 deletions(-) diff --git a/modules/juce_core/containers/juce_Array.h b/modules/juce_core/containers/juce_Array.h index 4b0ae52928..1d15933d6c 100644 --- a/modules/juce_core/containers/juce_Array.h +++ b/modules/juce_core/containers/juce_Array.h @@ -679,30 +679,23 @@ public: // avoids getting warning messages about the parameter being unused const ScopedLockType lock (getLock()); - int start = 0; - int end_ = numUsed; - for (;;) + for (int s = 0, e = numUsed;;) { - if (start >= end_) - { + if (s >= e) return -1; - } - else if (comparator.compareElements (elementToLookFor, data.elements [start]) == 0) - { - return start; - } - else - { - const int halfway = (start + end_) >> 1; - if (halfway == start) - return -1; - else if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0) - start = halfway; - else - end_ = halfway; - } + if (comparator.compareElements (elementToLookFor, data.elements [s]) == 0) + return s; + + const int halfway = (s + e) / 2; + if (halfway == s) + return -1; + + if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0) + s = halfway; + else + e = halfway; } } @@ -733,9 +726,7 @@ public: if (numberToShift > 0) memmove (e, e + 1, ((size_t) numberToShift) * sizeof (ElementType)); - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - + minimiseStorageAfterRemoval(); return removed; } else @@ -798,9 +789,7 @@ public: memmove (e, e + numberToRemove, ((size_t) numToShift) * sizeof (ElementType)); numUsed -= numberToRemove; - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); + minimiseStorageAfterRemoval(); } } @@ -820,9 +809,7 @@ public: data.elements [numUsed - i].~ElementType(); numUsed -= howManyToRemove; - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); + minimiseStorageAfterRemoval(); } /** Removes any elements which are also in another array. @@ -1029,6 +1016,12 @@ private: for (int i = 0; i < numUsed; ++i) data.elements[i].~ElementType(); } + + void minimiseStorageAfterRemoval() + { + if (data.numAllocated > numUsed * 2) + data.shrinkToNoMoreThan (jmax (numUsed, 64 / (int) sizeof (ElementType))); + } }; diff --git a/modules/juce_core/threads/juce_ReadWriteLock.cpp b/modules/juce_core/threads/juce_ReadWriteLock.cpp index a263e2a9fa..4e7ef20784 100644 --- a/modules/juce_core/threads/juce_ReadWriteLock.cpp +++ b/modules/juce_core/threads/juce_ReadWriteLock.cpp @@ -45,27 +45,22 @@ void ReadWriteLock::enterRead() const noexcept for (;;) { - jassert (readerThreads.size() % 2 == 0); - - int i; - for (i = 0; i < readerThreads.size(); i += 2) - if (readerThreads.getUnchecked(i) == threadId) - break; - - if (i < readerThreads.size() - || numWriters + numWaitingWriters == 0 - || (threadId == writerThreadId && numWriters > 0)) + for (int i = 0; i < readerThreads.size(); ++i) { - if (i < readerThreads.size()) - { - readerThreads.set (i + 1, (Thread::ThreadID) (1 + (pointer_sized_int) readerThreads.getUnchecked (i + 1))); - } - else - { - readerThreads.add (threadId); - readerThreads.add ((Thread::ThreadID) 1); - } + ThreadRecursionCount& trc = readerThreads.getReference(i); + if (trc.threadID == threadId) + { + trc.count++; + return; + } + } + + if (numWriters + numWaitingWriters == 0 + || (threadId == writerThreadId && numWriters > 0)) + { + ThreadRecursionCount trc = { threadId, 1 }; + readerThreads.add (trc); return; } @@ -79,21 +74,17 @@ void ReadWriteLock::exitRead() const noexcept const Thread::ThreadID threadId = Thread::getCurrentThreadId(); const SpinLock::ScopedLockType sl (accessLock); - for (int i = 0; i < readerThreads.size(); i += 2) + for (int i = 0; i < readerThreads.size(); ++i) { - if (readerThreads.getUnchecked(i) == threadId) - { - const pointer_sized_int newCount = ((pointer_sized_int) readerThreads.getUnchecked (i + 1)) - 1; + ThreadRecursionCount& trc = readerThreads.getReference(i); - if (newCount == 0) + if (trc.threadID == threadId) + { + if (--(trc.count) == 0) { - readerThreads.removeRange (i, 2); + readerThreads.remove (i); waitEvent.signal(); } - else - { - readerThreads.set (i + 1, (Thread::ThreadID) newCount); - } return; } @@ -112,8 +103,8 @@ void ReadWriteLock::enterWrite() const noexcept { if (readerThreads.size() + numWriters == 0 || threadId == writerThreadId - || (readerThreads.size() == 2 - && readerThreads.getUnchecked(0) == threadId)) + || (readerThreads.size() == 1 + && readerThreads.getReference(0).threadID == threadId)) { writerThreadId = threadId; ++numWriters; @@ -135,8 +126,8 @@ bool ReadWriteLock::tryEnterWrite() const noexcept if (readerThreads.size() + numWriters == 0 || threadId == writerThreadId - || (readerThreads.size() == 2 - && readerThreads.getUnchecked(0) == threadId)) + || (readerThreads.size() == 1 + && readerThreads.getReference(0).threadID == threadId)) { writerThreadId = threadId; ++numWriters; diff --git a/modules/juce_core/threads/juce_ReadWriteLock.h b/modules/juce_core/threads/juce_ReadWriteLock.h index 7b729a742e..0c45904144 100644 --- a/modules/juce_core/threads/juce_ReadWriteLock.h +++ b/modules/juce_core/threads/juce_ReadWriteLock.h @@ -129,7 +129,14 @@ private: WaitableEvent waitEvent; mutable int numWaitingWriters, numWriters; mutable Thread::ThreadID writerThreadId; - mutable Array readerThreads; + + struct ThreadRecursionCount + { + Thread::ThreadID threadID; + int count; + }; + + mutable Array readerThreads; JUCE_DECLARE_NON_COPYABLE (ReadWriteLock); };