@@ -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))); | |||
} | |||
}; | |||
@@ -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 | |||
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; | |||
} | |||
@@ -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; | |||
@@ -129,7 +129,14 @@ private: | |||
WaitableEvent waitEvent; | |||
mutable int numWaitingWriters, numWriters; | |||
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); | |||
}; | |||