@@ -679,30 +679,23 @@ public: | |||||
// avoids getting warning messages about the parameter being unused | // avoids getting warning messages about the parameter being unused | ||||
const ScopedLockType lock (getLock()); | 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; | 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) | if (numberToShift > 0) | ||||
memmove (e, e + 1, ((size_t) numberToShift) * sizeof (ElementType)); | memmove (e, e + 1, ((size_t) numberToShift) * sizeof (ElementType)); | ||||
if ((numUsed << 1) < data.numAllocated) | |||||
minimiseStorageOverheads(); | |||||
minimiseStorageAfterRemoval(); | |||||
return removed; | return removed; | ||||
} | } | ||||
else | else | ||||
@@ -798,9 +789,7 @@ public: | |||||
memmove (e, e + numberToRemove, ((size_t) numToShift) * sizeof (ElementType)); | memmove (e, e + numberToRemove, ((size_t) numToShift) * sizeof (ElementType)); | ||||
numUsed -= numberToRemove; | numUsed -= numberToRemove; | ||||
if ((numUsed << 1) < data.numAllocated) | |||||
minimiseStorageOverheads(); | |||||
minimiseStorageAfterRemoval(); | |||||
} | } | ||||
} | } | ||||
@@ -820,9 +809,7 @@ public: | |||||
data.elements [numUsed - i].~ElementType(); | data.elements [numUsed - i].~ElementType(); | ||||
numUsed -= howManyToRemove; | numUsed -= howManyToRemove; | ||||
if ((numUsed << 1) < data.numAllocated) | |||||
minimiseStorageOverheads(); | |||||
minimiseStorageAfterRemoval(); | |||||
} | } | ||||
/** Removes any elements which are also in another array. | /** Removes any elements which are also in another array. | ||||
@@ -1029,6 +1016,12 @@ private: | |||||
for (int i = 0; i < numUsed; ++i) | for (int i = 0; i < numUsed; ++i) | ||||
data.elements[i].~ElementType(); | data.elements[i].~ElementType(); | ||||
} | } | ||||
void minimiseStorageAfterRemoval() | |||||
{ | |||||
if (data.numAllocated > numUsed * 2) | |||||
data.shrinkToNoMoreThan (jmax (numUsed, 64 / (int) sizeof (ElementType))); | |||||
} | |||||
}; | }; | ||||
@@ -45,27 +45,22 @@ void ReadWriteLock::enterRead() const noexcept | |||||
for (;;) | 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 | |||||
ThreadRecursionCount& trc = readerThreads.getReference(i); | |||||
if (trc.threadID == threadId) | |||||
{ | { | ||||
readerThreads.add (threadId); | |||||
readerThreads.add ((Thread::ThreadID) 1); | |||||
trc.count++; | |||||
return; | |||||
} | } | ||||
} | |||||
if (numWriters + numWaitingWriters == 0 | |||||
|| (threadId == writerThreadId && numWriters > 0)) | |||||
{ | |||||
ThreadRecursionCount trc = { threadId, 1 }; | |||||
readerThreads.add (trc); | |||||
return; | return; | ||||
} | } | ||||
@@ -79,21 +74,17 @@ void ReadWriteLock::exitRead() const noexcept | |||||
const Thread::ThreadID threadId = Thread::getCurrentThreadId(); | const Thread::ThreadID threadId = Thread::getCurrentThreadId(); | ||||
const SpinLock::ScopedLockType sl (accessLock); | 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(); | waitEvent.signal(); | ||||
} | } | ||||
else | |||||
{ | |||||
readerThreads.set (i + 1, (Thread::ThreadID) newCount); | |||||
} | |||||
return; | return; | ||||
} | } | ||||
@@ -112,8 +103,8 @@ void ReadWriteLock::enterWrite() const noexcept | |||||
{ | { | ||||
if (readerThreads.size() + numWriters == 0 | if (readerThreads.size() + numWriters == 0 | ||||
|| threadId == writerThreadId | || threadId == writerThreadId | ||||
|| (readerThreads.size() == 2 | |||||
&& readerThreads.getUnchecked(0) == threadId)) | |||||
|| (readerThreads.size() == 1 | |||||
&& readerThreads.getReference(0).threadID == threadId)) | |||||
{ | { | ||||
writerThreadId = threadId; | writerThreadId = threadId; | ||||
++numWriters; | ++numWriters; | ||||
@@ -135,8 +126,8 @@ bool ReadWriteLock::tryEnterWrite() const noexcept | |||||
if (readerThreads.size() + numWriters == 0 | if (readerThreads.size() + numWriters == 0 | ||||
|| threadId == writerThreadId | || threadId == writerThreadId | ||||
|| (readerThreads.size() == 2 | |||||
&& readerThreads.getUnchecked(0) == threadId)) | |||||
|| (readerThreads.size() == 1 | |||||
&& readerThreads.getReference(0).threadID == threadId)) | |||||
{ | { | ||||
writerThreadId = threadId; | writerThreadId = threadId; | ||||
++numWriters; | ++numWriters; | ||||
@@ -129,7 +129,14 @@ private: | |||||
WaitableEvent waitEvent; | WaitableEvent waitEvent; | ||||
mutable int numWaitingWriters, numWriters; | mutable int numWaitingWriters, numWriters; | ||||
mutable Thread::ThreadID writerThreadId; | mutable Thread::ThreadID writerThreadId; | ||||
mutable Array <Thread::ThreadID> readerThreads; | |||||
struct ThreadRecursionCount | |||||
{ | |||||
Thread::ThreadID threadID; | |||||
int count; | |||||
}; | |||||
mutable Array <ThreadRecursionCount> readerThreads; | |||||
JUCE_DECLARE_NON_COPYABLE (ReadWriteLock); | JUCE_DECLARE_NON_COPYABLE (ReadWriteLock); | ||||
}; | }; | ||||