Browse Source

Modernised some old code.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
39b583fe1e
27 changed files with 945 additions and 1405 deletions
  1. +268
    -218
      juce_amalgamated.cpp
  2. +194
    -459
      juce_amalgamated.h
  3. +10
    -8
      src/audio/audio_sources/juce_AudioTransportSource.cpp
  4. +31
    -29
      src/audio/audio_sources/juce_BufferingAudioSource.cpp
  5. +26
    -16
      src/audio/audio_sources/juce_MixerAudioSource.cpp
  6. +7
    -4
      src/audio/devices/juce_AudioDeviceManager.cpp
  7. +15
    -13
      src/audio/devices/juce_MidiOutput.cpp
  8. +24
    -12
      src/audio/processors/juce_AudioProcessor.cpp
  9. +8
    -5
      src/audio/processors/juce_AudioProcessorPlayer.cpp
  10. +57
    -158
      src/containers/juce_Array.h
  11. +41
    -110
      src/containers/juce_OwnedArray.h
  12. +51
    -127
      src/containers/juce_ReferenceCountedArray.h
  13. +39
    -113
      src/containers/juce_SortedSet.h
  14. +37
    -33
      src/events/juce_MessageManager.cpp
  15. +5
    -3
      src/events/juce_MessageManager.h
  16. +9
    -5
      src/events/juce_Timer.cpp
  17. +9
    -6
      src/gui/components/controls/juce_TreeView.cpp
  18. +3
    -5
      src/io/streams/juce_OutputStream.cpp
  19. +8
    -6
      src/native/mac/juce_iphone_Audio.cpp
  20. +6
    -7
      src/native/mac/juce_mac_CoreAudio.cpp
  21. +6
    -7
      src/native/mac/juce_mac_CoreMidi.cpp
  22. +41
    -38
      src/native/windows/juce_win32_Midi.cpp
  23. +22
    -2
      src/threads/juce_CriticalSection.h
  24. +14
    -11
      src/threads/juce_Thread.cpp
  25. +3
    -0
      src/threads/juce_Thread.h
  26. +5
    -7
      src/threads/juce_ThreadPool.cpp
  27. +6
    -3
      src/utilities/juce_DeletedAtShutdown.cpp

+ 268
- 218
juce_amalgamated.cpp View File

@@ -5417,18 +5417,16 @@ void juce_CheckForDanglingStreams()
OutputStream::OutputStream() throw()
{
#if JUCE_DEBUG
activeStreamLock.enter();
const ScopedLock sl (activeStreamLock);
activeStreams.add (this);
activeStreamLock.exit();
#endif
}

OutputStream::~OutputStream()
{
#if JUCE_DEBUG
activeStreamLock.enter();
const ScopedLock sl (activeStreamLock);
activeStreams.removeValue (this);
activeStreamLock.exit();
#endif
}

@@ -15373,9 +15371,6 @@ void juce_setCurrentThreadName (const String& name);
void juce_CloseThreadHandle (void* handle);
#endif

static VoidArray runningThreads;
static CriticalSection runningThreadsLock;

void Thread::threadEntryPoint (Thread* const thread)
{
{
@@ -15573,7 +15568,7 @@ Thread* Thread::getCurrentThread()

for (int i = runningThreads.size(); --i >= 0;)
{
Thread* const t = (Thread*) runningThreads.getUnchecked(i);
Thread* const t = runningThreads.getUnchecked(i);

if (t->threadId_ == thisId)
return t;
@@ -15588,22 +15583,28 @@ void Thread::stopAllThreads (const int timeOutMilliseconds)
const ScopedLock sl (runningThreadsLock);

for (int i = runningThreads.size(); --i >= 0;)
((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit();
runningThreads.getUnchecked(i)->signalThreadShouldExit();
}

for (;;)
{
runningThreadsLock.enter();
Thread* const t = (Thread*) runningThreads[0];
runningThreadsLock.exit();
Thread* firstThread;

{
const ScopedLock sl (runningThreadsLock);
firstThread = runningThreads.getFirst();
}

if (t == 0)
if (firstThread == 0)
break;

t->stopThread (timeOutMilliseconds);
firstThread->stopThread (timeOutMilliseconds);
}
}

Array<Thread*> Thread::runningThreads;
CriticalSection Thread::runningThreadsLock;

END_JUCE_NAMESPACE
/*** End of inlined file: juce_Thread.cpp ***/

@@ -15796,9 +15797,11 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job,
const bool interruptIfRunning,
const int timeOutMs)
{
bool dontWait = true;

if (job != 0)
{
lock.enter();
const ScopedLock sl (lock);

if (jobs.contains (job))
{
@@ -15807,20 +15810,16 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job,
if (interruptIfRunning)
job->signalJobShouldExit();

lock.exit();

return waitForJobToFinish (job, timeOutMs);
dontWait = false;
}
else
{
jobs.removeValue (job);
}
}

lock.exit();
}

return true;
return dontWait || waitForJobToFinish (job, timeOutMs);
}

bool ThreadPool::removeAllJobs (const bool interruptRunningJobs,
@@ -18016,9 +18015,12 @@ void DeletedAtShutdown::deleteAll()
{
// make a local copy of the array, so it can't get into a loop if something
// creates another DeletedAtShutdown object during its destructor.
lock.enter();
const VoidArray localCopy (objectsToDelete);
lock.exit();
VoidArray localCopy;

{
const ScopedLock sl (lock);
localCopy = objectsToDelete;
}

for (int i = localCopy.size(); --i >= 0;)
{
@@ -22950,11 +22952,12 @@ void AudioTransportSource::start()
{
if ((! playing) && masterSource != 0)
{
callbackLock.enter();
playing = true;
stopped = false;
inputStreamEOF = false;
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
playing = true;
stopped = false;
inputStreamEOF = false;
}

sendChangeMessage (this);
}
@@ -22964,9 +22967,10 @@ void AudioTransportSource::stop()
{
if (playing)
{
callbackLock.enter();
playing = false;
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
playing = false;
}

int n = 500;
while (--n >= 0 && ! stopped)
@@ -23350,45 +23354,47 @@ void BufferingAudioSource::setNextReadPosition (int newPosition)

bool BufferingAudioSource::readNextBufferChunk()
{
bufferStartPosLock.enter();
int newBVS, newBVE, sectionToReadStart, sectionToReadEnd;

if (wasSourceLooping != isLooping())
{
wasSourceLooping = isLooping();
bufferValidStart = 0;
bufferValidEnd = 0;
}
const ScopedLock sl (bufferStartPosLock);

int newBVS = jmax (0, nextPlayPos);
int newBVE = newBVS + buffer.getNumSamples() - 4;
int sectionToReadStart = 0;
int sectionToReadEnd = 0;
if (wasSourceLooping != isLooping())
{
wasSourceLooping = isLooping();
bufferValidStart = 0;
bufferValidEnd = 0;
}

const int maxChunkSize = 2048;
newBVS = jmax (0, nextPlayPos);
newBVE = newBVS + buffer.getNumSamples() - 4;
sectionToReadStart = 0;
sectionToReadEnd = 0;

if (newBVS < bufferValidStart || newBVS >= bufferValidEnd)
{
newBVE = jmin (newBVE, newBVS + maxChunkSize);
const int maxChunkSize = 2048;

sectionToReadStart = newBVS;
sectionToReadEnd = newBVE;
if (newBVS < bufferValidStart || newBVS >= bufferValidEnd)
{
newBVE = jmin (newBVE, newBVS + maxChunkSize);

bufferValidStart = 0;
bufferValidEnd = 0;
}
else if (abs (newBVS - bufferValidStart) > 512
|| abs (newBVE - bufferValidEnd) > 512)
{
newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize);
sectionToReadStart = newBVS;
sectionToReadEnd = newBVE;

sectionToReadStart = bufferValidEnd;
sectionToReadEnd = newBVE;
bufferValidStart = 0;
bufferValidEnd = 0;
}
else if (abs (newBVS - bufferValidStart) > 512
|| abs (newBVE - bufferValidEnd) > 512)
{
newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize);

bufferValidStart = newBVS;
bufferValidEnd = jmin (bufferValidEnd, newBVE);
}
sectionToReadStart = bufferValidEnd;
sectionToReadEnd = newBVE;

bufferStartPosLock.exit();
bufferValidStart = newBVS;
bufferValidEnd = jmin (bufferValidEnd, newBVE);
}
}

if (sectionToReadStart != sectionToReadEnd)
{
@@ -23696,10 +23702,14 @@ void MixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhen
{
if (input != 0 && ! inputs.contains (input))
{
lock.enter();
double localRate = currentSampleRate;
int localBufferSize = bufferSizeExpected;
lock.exit();
double localRate;
int localBufferSize;

{
const ScopedLock sl (lock);
localRate = currentSampleRate;
localBufferSize = bufferSizeExpected;
}

if (localRate != 0.0)
input->prepareToPlay (localBufferSize, localRate);
@@ -23715,16 +23725,19 @@ void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteI
{
if (input != 0)
{
lock.enter();
const int index = inputs.indexOf ((void*) input);
int index;

if (index >= 0)
{
inputsToDelete.shiftBits (index, 1);
inputs.remove (index);
}
const ScopedLock sl (lock);

lock.exit();
index = inputs.indexOf ((void*) input);

if (index >= 0)
{
inputsToDelete.shiftBits (index, 1);
inputs.remove (index);
}
}

if (index >= 0)
{
@@ -23738,11 +23751,14 @@ void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteI

void MixerAudioSource::removeAllInputs()
{
lock.enter();
VoidArray inputsCopy (inputs);
BitArray inputsToDeleteCopy (inputsToDelete);
inputs.clear();
lock.exit();
VoidArray inputsCopy;
BitArray inputsToDeleteCopy;

{
const ScopedLock sl (lock);
inputsCopy = inputs;
inputsToDeleteCopy = inputsToDelete;
}

for (int i = inputsCopy.size(); --i >= 0;)
if (inputsToDeleteCopy[i])
@@ -24987,10 +25003,13 @@ void AudioDeviceManager::CallbackHandler::handleIncomingMidiMessage (MidiInput*

void AudioDeviceManager::playTestSound()
{
{
audioCallbackLock.enter();
ScopedPointer <AudioSampleBuffer> oldSound (testSound);
audioCallbackLock.exit();
{ // cunningly nested to swap, unlock and delete in that order.
ScopedPointer <AudioSampleBuffer> oldSound;

{
const ScopedLock sl (audioCallbackLock);
oldSound = testSound;
}
}

testSoundPosition = 0;
@@ -25179,26 +25198,28 @@ void MidiOutput::run()
uint32 eventTime = 0;
uint32 timeToWait = 500;

lock.enter();
PendingMessage* message = firstMessage;
PendingMessage* message;

if (message != 0)
{
eventTime = roundToInt (message->message.getTimeStamp());
const ScopedLock sl (lock);
message = firstMessage;

if (eventTime > now + 20)
{
timeToWait = eventTime - (now + 20);
message = 0;
}
else
if (message != 0)
{
firstMessage = message->next;
eventTime = roundToInt (message->message.getTimeStamp());

if (eventTime > now + 20)
{
timeToWait = eventTime - (now + 20);
message = 0;
}
else
{
firstMessage = message->next;
}
}
}

lock.exit();

if (message != 0)
{
if (eventTime > now)
@@ -34679,9 +34700,12 @@ void AudioProcessor::sendParamChangeMessageToListeners (const int parameterIndex

for (int i = listeners.size(); --i >= 0;)
{
listenerLock.enter();
AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i];
listenerLock.exit();
AudioProcessorListener* l;

{
const ScopedLock sl (listenerLock);
l = (AudioProcessorListener*) listeners [i];
}

if (l != 0)
l->audioProcessorParameterChanged (this, parameterIndex, newValue);
@@ -34701,9 +34725,12 @@ void AudioProcessor::beginParameterChangeGesture (int parameterIndex)

for (int i = listeners.size(); --i >= 0;)
{
listenerLock.enter();
AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i];
listenerLock.exit();
AudioProcessorListener* l;

{
const ScopedLock sl (listenerLock);
l = (AudioProcessorListener*) listeners [i];
}

if (l != 0)
l->audioProcessorParameterChangeGestureBegin (this, parameterIndex);
@@ -34724,9 +34751,12 @@ void AudioProcessor::endParameterChangeGesture (int parameterIndex)

for (int i = listeners.size(); --i >= 0;)
{
listenerLock.enter();
AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i];
listenerLock.exit();
AudioProcessorListener* l;

{
const ScopedLock sl (listenerLock);
l = (AudioProcessorListener*) listeners [i];
}

if (l != 0)
l->audioProcessorParameterChangeGestureEnd (this, parameterIndex);
@@ -34737,9 +34767,12 @@ void AudioProcessor::updateHostDisplay()
{
for (int i = listeners.size(); --i >= 0;)
{
listenerLock.enter();
AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i];
listenerLock.exit();
AudioProcessorListener* l;

{
const ScopedLock sl (listenerLock);
l = (AudioProcessorListener*) listeners [i];
}

if (l != 0)
l->audioProcessorChanged (this);
@@ -36211,11 +36244,14 @@ void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay)
processorToPlay->prepareToPlay (sampleRate, blockSize);
}

lock.enter();
AudioProcessor* const oldOne = isPrepared ? processor : 0;
processor = processorToPlay;
isPrepared = true;
lock.exit();
AudioProcessor* oldOne;

{
const ScopedLock sl (lock);
oldOne = isPrepared ? processor : 0;
processor = processorToPlay;
isPrepared = true;
}

if (oldOne != 0)
oldOne->releaseResources();
@@ -37963,25 +37999,24 @@ bool MessageManager::currentThreadHasLockedMessageManager() const throw()
return thisThread == messageThreadId || thisThread == threadWithLock;
}

class SharedLockingEvents : public ReferenceCountedObject
class MessageManagerLock::SharedEvents : public ReferenceCountedObject
{
public:
SharedLockingEvents() throw() {}
~SharedLockingEvents() {}
SharedEvents() {}
~SharedEvents() {}

WaitableEvent lockedEvent, releaseEvent;

private:
SharedEvents (const SharedEvents&);
SharedEvents& operator= (const SharedEvents&);
};

class MMLockMessage : public CallbackMessage
class MessageManagerLock::BlockingMessage : public CallbackMessage
{
public:
MMLockMessage (SharedLockingEvents* const events_) throw()
: events (events_)
{}

~MMLockMessage() throw() {}

ReferenceCountedObjectPtr <SharedLockingEvents> events;
BlockingMessage (MessageManagerLock::SharedEvents* const events_) : events (events_) {}
~BlockingMessage() throw() {}

void messageCallback()
{
@@ -37991,20 +38026,23 @@ public:

juce_UseDebuggingNewOperator

MMLockMessage (const MMLockMessage&);
const MMLockMessage& operator= (const MMLockMessage&);
private:
ReferenceCountedObjectPtr <MessageManagerLock::SharedEvents> events;

BlockingMessage (const BlockingMessage&);
BlockingMessage& operator= (const BlockingMessage&);
};

MessageManagerLock::MessageManagerLock (Thread* const threadToCheck) throw()
: locked (false),
needsUnlocking (false)
: sharedEvents (0),
locked (false)
{
init (threadToCheck, 0);
}

MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw()
: locked (false),
needsUnlocking (false)
: sharedEvents (0),
locked (false)
{
init (0, jobToCheckForExitSignal);
}
@@ -38035,19 +38073,19 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const
}
}

SharedLockingEvents* const events = new SharedLockingEvents();
sharedEvents = events;
events->incReferenceCount();
sharedEvents = new SharedEvents();
sharedEvents->incReferenceCount();

(new MMLockMessage (events))->post();
(new BlockingMessage (sharedEvents))->post();

while (! events->lockedEvent.wait (50))
while (! sharedEvents->lockedEvent.wait (50))
{
if ((threadToCheck != 0 && threadToCheck->threadShouldExit())
|| (job != 0 && job->shouldExit()))
{
events->releaseEvent.signal();
events->decReferenceCount();
sharedEvents->releaseEvent.signal();
sharedEvents->decReferenceCount();
sharedEvents = 0;
MessageManager::instance->lockingLock.exit();
return;
}
@@ -38057,21 +38095,24 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const

MessageManager::instance->threadWithLock = Thread::getCurrentThreadId();
locked = true;
needsUnlocking = true;
}
}
}

MessageManagerLock::~MessageManagerLock() throw()
{
if (needsUnlocking && MessageManager::instance != 0)
if (sharedEvents != 0)
{
jassert (MessageManager::instance->currentThreadHasLockedMessageManager());
jassert (MessageManager::instance == 0 || MessageManager::instance->currentThreadHasLockedMessageManager());

sharedEvents->releaseEvent.signal();
sharedEvents->decReferenceCount();

((SharedLockingEvents*) sharedEvents)->releaseEvent.signal();
((SharedLockingEvents*) sharedEvents)->decReferenceCount();
MessageManager::instance->threadWithLock = 0;
MessageManager::instance->lockingLock.exit();
if (MessageManager::instance != 0)
{
MessageManager::instance->threadWithLock = 0;
MessageManager::instance->lockingLock.exit();
}
}
}

@@ -38228,11 +38269,15 @@ public:
const int elapsed = now - lastTime;
lastTime = now;

lock.enter();
decrementAllCounters (elapsed);
const int timeUntilFirstTimer = (firstTimer != 0) ? firstTimer->countdownMs
: 1000;
lock.exit();
int timeUntilFirstTimer = 1000;

{
const ScopedLock sl (lock);
decrementAllCounters (elapsed);

if (firstTimer != 0)
timeUntilFirstTimer = firstTimer->countdownMs;
}

if (timeUntilFirstTimer <= 0)
{
@@ -56299,16 +56344,19 @@ void TreeViewItem::addSubItem (TreeViewItem* const newItem, const int insertPosi
void TreeViewItem::removeSubItem (const int index, const bool deleteItem)
{
if (ownerView != 0)
ownerView->nodeAlterationLock.enter();
{
const ScopedLock sl (ownerView->nodeAlterationLock);

if (((unsigned int) index) < (unsigned int) subItems.size())
if (((unsigned int) index) < (unsigned int) subItems.size())
{
subItems.remove (index, deleteItem);
treeHasChanged();
}
}
else
{
subItems.remove (index, deleteItem);
treeHasChanged();
}

if (ownerView != 0)
ownerView->nodeAlterationLock.exit();
}

bool TreeViewItem::isOpen() const throw()
@@ -222335,24 +222383,25 @@ public:
return;

const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte);

const double time = timeStampToTime (timeStamp);

lock.enter();
if (pendingLength < midiBufferSize - 12)
{
char* const p = pending + pendingLength;
*(double*) p = time;
*(uint32*) (p + 8) = numBytes;
*(uint32*) (p + 12) = message;
pendingLength += 12 + numBytes;
}
else
{
jassertfalse // midi buffer overflow! You might need to increase the size..
const ScopedLock sl (lock);

if (pendingLength < midiBufferSize - 12)
{
char* const p = pending + pendingLength;
*(double*) p = time;
*(uint32*) (p + 8) = numBytes;
*(uint32*) (p + 12) = message;
pendingLength += 12 + numBytes;
}
else
{
jassertfalse // midi buffer overflow! You might need to increase the size..
}
}

lock.exit();
notify();
}

@@ -222364,22 +222413,23 @@ public:
{
const double time = timeStampToTime (timeStamp);

lock.enter();

if (pendingLength < midiBufferSize - (8 + num))
{
char* const p = pending + pendingLength;
*(double*) p = time;
*(uint32*) (p + 8) = num;
memcpy (p + 12, hdr->lpData, num);
pendingLength += 12 + num;
}
else
{
jassertfalse // midi buffer overflow! You might need to increase the size..
const ScopedLock sl (lock);

if (pendingLength < midiBufferSize - (8 + num))
{
char* const p = pending + pendingLength;
*(double*) p = time;
*(uint32*) (p + 8) = num;
memcpy (p + 12, hdr->lpData, num);
pendingLength += 12 + num;
}
else
{
jassertfalse // midi buffer overflow! You might need to increase the size..
}
}

lock.exit();
notify();
}
}
@@ -222410,20 +222460,22 @@ public:
}
}

lock.enter();
int len;

int len = pendingLength;

if (len > 0)
{
pendingCopy.ensureSize (len);
pendingCopy.copyFrom (pending, 0, len);
pendingLength = 0;
}
const ScopedLock sl (lock);

lock.exit();
len = pendingLength;

if (len > 0)
{
pendingCopy.ensureSize (len);
pendingCopy.copyFrom (pending, 0, len);
pendingLength = 0;
}
}

//xxx needs to figure out if blocks are broken up or not
//xxx needs to figure out if blocks are broken up or not

if (len == 0)
{
@@ -222487,8 +222539,7 @@ public:

activeMidiThreads.removeValue (this);

lock.enter();
lock.exit();
{ const ScopedLock sl (lock); }

for (int i = numInHeaders; --i >= 0;)
{
@@ -242981,9 +243032,8 @@ public:
if (callback_ != 0)
callback_->audioDeviceAboutToStart (this);

callbackLock.enter();
const ScopedLock sl (callbackLock);
callback = callback_;
callbackLock.exit();
}
}

@@ -242991,10 +243041,13 @@ public:
{
if (isRunning)
{
callbackLock.enter();
AudioIODeviceCallback* const lastCallback = callback;
callback = 0;
callbackLock.exit();
AudioIODeviceCallback* lastCallback;

{
const ScopedLock sl (callbackLock);
lastCallback = callback;
callback = 0;
}

if (lastCallback != 0)
lastCallback->audioDeviceStopped();
@@ -243939,9 +243992,10 @@ MidiInput::~MidiInput()
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
mpc->active = false;

callbackLock.enter();
activeCallbacks.removeValue (mpc);
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
activeCallbacks.removeValue (mpc);
}

if (mpc->portAndEndpoint->port != 0)
OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint));
@@ -243952,16 +244006,14 @@ MidiInput::~MidiInput()

void MidiInput::start()
{
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
const ScopedLock sl (callbackLock);
mpc->active = true;
((MidiPortAndCallback*) internal)->active = true;
}

void MidiInput::stop()
{
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
const ScopedLock sl (callbackLock);
mpc->active = false;
((MidiPortAndCallback*) internal)->active = false;
}

#undef log
@@ -250475,9 +250527,10 @@ public:

void stop (bool leaveInterruptRunning)
{
callbackLock.enter();
callback = 0;
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
callback = 0;
}

if (started
&& (deviceID != 0)
@@ -250493,8 +250546,7 @@ public:
#endif
started = false;

callbackLock.enter();
callbackLock.exit();
{ const ScopedLock sl (callbackLock); }

// wait until it's definately stopped calling back..
for (int i = 40; --i >= 0;)
@@ -250515,8 +250567,7 @@ public:
break;
}

callbackLock.enter();
callbackLock.exit();
const ScopedLock sl (callbackLock);
}

if (inputDevice != 0)
@@ -251850,9 +251901,10 @@ MidiInput::~MidiInput()
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
mpc->active = false;

callbackLock.enter();
activeCallbacks.removeValue (mpc);
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
activeCallbacks.removeValue (mpc);
}

if (mpc->portAndEndpoint->port != 0)
OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint));
@@ -251863,16 +251915,14 @@ MidiInput::~MidiInput()

void MidiInput::start()
{
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
const ScopedLock sl (callbackLock);
mpc->active = true;
((MidiPortAndCallback*) internal)->active = true;
}

void MidiInput::stop()
{
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
const ScopedLock sl (callbackLock);
mpc->active = false;
((MidiPortAndCallback*) internal)->active = false;
}

#undef log


+ 194
- 459
juce_amalgamated.h
File diff suppressed because it is too large
View File


+ 10
- 8
src/audio/audio_sources/juce_AudioTransportSource.cpp View File

@@ -128,11 +128,12 @@ void AudioTransportSource::start()
{
if ((! playing) && masterSource != 0)
{
callbackLock.enter();
playing = true;
stopped = false;
inputStreamEOF = false;
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
playing = true;
stopped = false;
inputStreamEOF = false;
}
sendChangeMessage (this);
}
@@ -142,9 +143,10 @@ void AudioTransportSource::stop()
{
if (playing)
{
callbackLock.enter();
playing = false;
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
playing = false;
}
int n = 500;
while (--n >= 0 && ! stopped)


+ 31
- 29
src/audio/audio_sources/juce_BufferingAudioSource.cpp View File

@@ -269,45 +269,47 @@ void BufferingAudioSource::setNextReadPosition (int newPosition)
bool BufferingAudioSource::readNextBufferChunk()
{
bufferStartPosLock.enter();
int newBVS, newBVE, sectionToReadStart, sectionToReadEnd;
if (wasSourceLooping != isLooping())
{
wasSourceLooping = isLooping();
bufferValidStart = 0;
bufferValidEnd = 0;
}
const ScopedLock sl (bufferStartPosLock);
int newBVS = jmax (0, nextPlayPos);
int newBVE = newBVS + buffer.getNumSamples() - 4;
int sectionToReadStart = 0;
int sectionToReadEnd = 0;
if (wasSourceLooping != isLooping())
{
wasSourceLooping = isLooping();
bufferValidStart = 0;
bufferValidEnd = 0;
}
const int maxChunkSize = 2048;
newBVS = jmax (0, nextPlayPos);
newBVE = newBVS + buffer.getNumSamples() - 4;
sectionToReadStart = 0;
sectionToReadEnd = 0;
if (newBVS < bufferValidStart || newBVS >= bufferValidEnd)
{
newBVE = jmin (newBVE, newBVS + maxChunkSize);
const int maxChunkSize = 2048;
sectionToReadStart = newBVS;
sectionToReadEnd = newBVE;
if (newBVS < bufferValidStart || newBVS >= bufferValidEnd)
{
newBVE = jmin (newBVE, newBVS + maxChunkSize);
bufferValidStart = 0;
bufferValidEnd = 0;
}
else if (abs (newBVS - bufferValidStart) > 512
|| abs (newBVE - bufferValidEnd) > 512)
{
newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize);
sectionToReadStart = newBVS;
sectionToReadEnd = newBVE;
sectionToReadStart = bufferValidEnd;
sectionToReadEnd = newBVE;
bufferValidStart = 0;
bufferValidEnd = 0;
}
else if (abs (newBVS - bufferValidStart) > 512
|| abs (newBVE - bufferValidEnd) > 512)
{
newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize);
bufferValidStart = newBVS;
bufferValidEnd = jmin (bufferValidEnd, newBVE);
}
sectionToReadStart = bufferValidEnd;
sectionToReadEnd = newBVE;
bufferStartPosLock.exit();
bufferValidStart = newBVS;
bufferValidEnd = jmin (bufferValidEnd, newBVE);
}
}
if (sectionToReadStart != sectionToReadEnd)
{


+ 26
- 16
src/audio/audio_sources/juce_MixerAudioSource.cpp View File

@@ -49,10 +49,14 @@ void MixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhen
{
if (input != 0 && ! inputs.contains (input))
{
lock.enter();
double localRate = currentSampleRate;
int localBufferSize = bufferSizeExpected;
lock.exit();
double localRate;
int localBufferSize;
{
const ScopedLock sl (lock);
localRate = currentSampleRate;
localBufferSize = bufferSizeExpected;
}
if (localRate != 0.0)
input->prepareToPlay (localBufferSize, localRate);
@@ -68,16 +72,19 @@ void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteI
{
if (input != 0)
{
lock.enter();
const int index = inputs.indexOf ((void*) input);
int index;
if (index >= 0)
{
inputsToDelete.shiftBits (index, 1);
inputs.remove (index);
}
const ScopedLock sl (lock);
lock.exit();
index = inputs.indexOf ((void*) input);
if (index >= 0)
{
inputsToDelete.shiftBits (index, 1);
inputs.remove (index);
}
}
if (index >= 0)
{
@@ -91,11 +98,14 @@ void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteI
void MixerAudioSource::removeAllInputs()
{
lock.enter();
VoidArray inputsCopy (inputs);
BitArray inputsToDeleteCopy (inputsToDelete);
inputs.clear();
lock.exit();
VoidArray inputsCopy;
BitArray inputsToDeleteCopy;
{
const ScopedLock sl (lock);
inputsCopy = inputs;
inputsToDeleteCopy = inputsToDelete;
}
for (int i = inputsCopy.size(); --i >= 0;)
if (inputsToDeleteCopy[i])


+ 7
- 4
src/audio/devices/juce_AudioDeviceManager.cpp View File

@@ -919,10 +919,13 @@ void AudioDeviceManager::CallbackHandler::handleIncomingMidiMessage (MidiInput*
//==============================================================================
void AudioDeviceManager::playTestSound()
{
{
audioCallbackLock.enter();
ScopedPointer <AudioSampleBuffer> oldSound (testSound);
audioCallbackLock.exit();
{ // cunningly nested to swap, unlock and delete in that order.
ScopedPointer <AudioSampleBuffer> oldSound;
{
const ScopedLock sl (audioCallbackLock);
oldSound = testSound;
}
}
testSoundPosition = 0;


+ 15
- 13
src/audio/devices/juce_MidiOutput.cpp View File

@@ -123,26 +123,28 @@ void MidiOutput::run()
uint32 eventTime = 0;
uint32 timeToWait = 500;
lock.enter();
PendingMessage* message = firstMessage;
PendingMessage* message;
if (message != 0)
{
eventTime = roundToInt (message->message.getTimeStamp());
const ScopedLock sl (lock);
message = firstMessage;
if (eventTime > now + 20)
{
timeToWait = eventTime - (now + 20);
message = 0;
}
else
if (message != 0)
{
firstMessage = message->next;
eventTime = roundToInt (message->message.getTimeStamp());
if (eventTime > now + 20)
{
timeToWait = eventTime - (now + 20);
message = 0;
}
else
{
firstMessage = message->next;
}
}
}
lock.exit();
if (message != 0)
{
if (eventTime > now)


+ 24
- 12
src/audio/processors/juce_AudioProcessor.cpp View File

@@ -114,9 +114,12 @@ void AudioProcessor::sendParamChangeMessageToListeners (const int parameterIndex
for (int i = listeners.size(); --i >= 0;)
{
listenerLock.enter();
AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i];
listenerLock.exit();
AudioProcessorListener* l;
{
const ScopedLock sl (listenerLock);
l = (AudioProcessorListener*) listeners [i];
}
if (l != 0)
l->audioProcessorParameterChanged (this, parameterIndex, newValue);
@@ -136,9 +139,12 @@ void AudioProcessor::beginParameterChangeGesture (int parameterIndex)
for (int i = listeners.size(); --i >= 0;)
{
listenerLock.enter();
AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i];
listenerLock.exit();
AudioProcessorListener* l;
{
const ScopedLock sl (listenerLock);
l = (AudioProcessorListener*) listeners [i];
}
if (l != 0)
l->audioProcessorParameterChangeGestureBegin (this, parameterIndex);
@@ -159,9 +165,12 @@ void AudioProcessor::endParameterChangeGesture (int parameterIndex)
for (int i = listeners.size(); --i >= 0;)
{
listenerLock.enter();
AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i];
listenerLock.exit();
AudioProcessorListener* l;
{
const ScopedLock sl (listenerLock);
l = (AudioProcessorListener*) listeners [i];
}
if (l != 0)
l->audioProcessorParameterChangeGestureEnd (this, parameterIndex);
@@ -172,9 +181,12 @@ void AudioProcessor::updateHostDisplay()
{
for (int i = listeners.size(); --i >= 0;)
{
listenerLock.enter();
AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i];
listenerLock.exit();
AudioProcessorListener* l;
{
const ScopedLock sl (listenerLock);
l = (AudioProcessorListener*) listeners [i];
}
if (l != 0)
l->audioProcessorChanged (this);


+ 8
- 5
src/audio/processors/juce_AudioProcessorPlayer.cpp View File

@@ -61,11 +61,14 @@ void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay)
processorToPlay->prepareToPlay (sampleRate, blockSize);
}
lock.enter();
AudioProcessor* const oldOne = isPrepared ? processor : 0;
processor = processorToPlay;
isPrepared = true;
lock.exit();
AudioProcessor* oldOne;
{
const ScopedLock sl (lock);
oldOne = isPrepared ? processor : 0;
processor = processorToPlay;
isPrepared = true;
}
if (oldOne != 0)
oldOne->releaseResources();


+ 57
- 158
src/containers/juce_Array.h View File

@@ -72,14 +72,12 @@ public:
*/
Array (const Array<ElementType, TypeOfCriticalSectionToUse>& other)
{
other.lockArray();
const ScopedLockType lock (other.getLock());
numUsed = other.numUsed;
data.setAllocatedSize (other.numUsed);
for (int i = 0; i < numUsed; ++i)
new (data.elements + i) ElementType (other.data.elements[i]);
other.unlockArray();
}
/** Initalises from a null-terminated C array of values.
@@ -117,7 +115,7 @@ public:
/** Copies another array.
@param other the array to copy
*/
Array <ElementType, TypeOfCriticalSectionToUse>& operator= (const Array <ElementType, TypeOfCriticalSectionToUse>& other)
Array& operator= (const Array& other)
{
if (this != &other)
{
@@ -137,24 +135,15 @@ public:
template <class OtherArrayType>
bool operator== (const OtherArrayType& other) const
{
data.enter();
const ScopedLockType lock (getLock());
if (numUsed != other.numUsed)
{
data.exit();
return false;
}
for (int i = numUsed; --i >= 0;)
{
if (data.elements [i] != other.data.elements [i])
{
data.exit();
return false;
}
}
data.exit();
return true;
}
@@ -179,14 +168,13 @@ public:
*/
void clear()
{
data.enter();
const ScopedLockType lock (getLock());
for (int i = 0; i < numUsed; ++i)
data.elements[i].~ElementType();
data.setAllocatedSize (0);
numUsed = 0;
data.exit();
}
/** Removes all elements from the array without freeing the array's allocated storage.
@@ -195,13 +183,12 @@ public:
*/
void clearQuick()
{
data.enter();
const ScopedLockType lock (getLock());
for (int i = 0; i < numUsed; ++i)
data.elements[i].~ElementType();
numUsed = 0;
data.exit();
}
//==============================================================================
@@ -224,13 +211,9 @@ public:
*/
inline ElementType operator[] (const int index) const
{
data.enter();
const ElementType result ((((unsigned int) index) < (unsigned int) numUsed)
? data.elements [index]
: ElementType());
data.exit();
return result;
const ScopedLockType lock (getLock());
return (((unsigned int) index) < (unsigned int) numUsed) ? data.elements [index]
: ElementType();
}
/** Returns one of the elements in the array, without checking the index passed in.
@@ -244,12 +227,9 @@ public:
*/
inline const ElementType getUnchecked (const int index) const
{
data.enter();
const ScopedLockType lock (getLock());
jassert (((unsigned int) index) < (unsigned int) numUsed);
const ElementType result (data.elements [index]);
data.exit();
return result;
return data.elements [index];
}
/** Returns a direct reference to one of the elements in the array, without checking the index passed in.
@@ -263,11 +243,9 @@ public:
*/
inline ElementType& getReference (const int index) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
jassert (((unsigned int) index) < (unsigned int) numUsed);
ElementType& result = data.elements [index];
data.exit();
return result;
return data.elements [index];
}
/** Returns the first element in the array, or 0 if the array is empty.
@@ -276,12 +254,9 @@ public:
*/
inline ElementType getFirst() const
{
data.enter();
const ElementType result ((numUsed > 0) ? data.elements [0]
: ElementType());
data.exit();
return result;
const ScopedLockType lock (getLock());
return (numUsed > 0) ? data.elements [0]
: ElementType();
}
/** Returns the last element in the array, or 0 if the array is empty.
@@ -290,12 +265,9 @@ public:
*/
inline ElementType getLast() const
{
data.enter();
const ElementType result ((numUsed > 0) ? data.elements [numUsed - 1]
: ElementType());
data.exit();
return result;
const ScopedLockType lock (getLock());
return (numUsed > 0) ? data.elements [numUsed - 1]
: ElementType();
}
//==============================================================================
@@ -309,24 +281,18 @@ public:
*/
int indexOf (const ElementType& elementToLookFor) const
{
int result = -1;
data.enter();
const ScopedLockType lock (getLock());
const ElementType* e = data.elements;
for (int i = numUsed; --i >= 0;)
{
if (elementToLookFor == *e)
{
result = (int) (e - data.elements);
break;
}
return (int) (e - data.elements);
++e;
}
data.exit();
return result;
return -1;
}
/** Returns true if the array contains at least one occurrence of an object.
@@ -336,24 +302,19 @@ public:
*/
bool contains (const ElementType& elementToLookFor) const
{
data.enter();
const ScopedLockType lock (getLock());
const ElementType* e = data.elements;
int num = numUsed;
while (num > 0)
{
if (elementToLookFor == *e)
{
data.exit();
return true;
}
--num;
++e;
}
data.exit();
return false;
}
@@ -365,10 +326,9 @@ public:
*/
void add (const ElementType& newElement)
{
data.enter();
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + 1);
new (data.elements + numUsed++) ElementType (newElement);
data.exit();
}
/** Inserts a new element into the array at a given position.
@@ -385,7 +345,7 @@ public:
*/
void insert (int indexToInsertAt, const ElementType& newElement)
{
data.enter();
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + 1);
if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed)
@@ -403,8 +363,6 @@ public:
{
new (data.elements + numUsed++) ElementType (newElement);
}
data.exit();
}
/** Inserts multiple copies of an element into the array at a given position.
@@ -424,7 +382,7 @@ public:
{
if (numberOfTimesToInsertIt > 0)
{
data.enter();
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt);
ElementType* insertPos;
@@ -443,8 +401,6 @@ public:
while (--numberOfTimesToInsertIt >= 0)
new (insertPos++) ElementType (newElement);
data.exit();
}
}
@@ -466,7 +422,7 @@ public:
{
if (numberOfElements > 0)
{
data.enter();
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + numberOfElements);
ElementType* insertPos;
@@ -485,8 +441,6 @@ public:
while (--numberOfElements >= 0)
new (insertPos++) ElementType (*newElements++);
data.exit();
}
}
@@ -500,12 +454,10 @@ public:
*/
void addIfNotAlreadyThere (const ElementType& newElement)
{
data.enter();
const ScopedLockType lock (getLock());
if (! contains (newElement))
add (newElement);
data.exit();
}
/** Replaces an element with a new value.
@@ -520,8 +472,7 @@ public:
void set (const int indexToChange, const ElementType& newValue)
{
jassert (indexToChange >= 0);
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) indexToChange) < (unsigned int) numUsed)
{
@@ -532,8 +483,6 @@ public:
data.ensureAllocatedSize (numUsed + 1);
new (data.elements + numUsed++) ElementType (newValue);
}
data.exit();
}
/** Replaces an element with a new value without doing any bounds-checking.
@@ -547,10 +496,9 @@ public:
*/
void setUnchecked (const int indexToChange, const ElementType& newValue)
{
data.enter();
const ScopedLockType lock (getLock());
jassert (((unsigned int) indexToChange) < (unsigned int) numUsed);
data.elements [indexToChange] = newValue;
data.exit();
}
/** Adds elements from an array to the end of this array.
@@ -561,7 +509,7 @@ public:
*/
void addArray (const ElementType* elementsToAdd, int numElementsToAdd)
{
data.enter();
const ScopedLockType lock (getLock());
if (numElementsToAdd > 0)
{
@@ -570,8 +518,6 @@ public:
while (--numElementsToAdd >= 0)
new (data.elements + numUsed++) ElementType (*elementsToAdd++);
}
data.exit();
}
/** This swaps the contents of this array with those of another array.
@@ -579,14 +525,13 @@ public:
If you need to exchange two arrays, this is vastly quicker than using copy-by-value
because it just swaps their internal pointers.
*/
void swapWithArray (Array <ElementType>& otherArray) throw()
void swapWithArray (Array& otherArray) throw()
{
data.enter();
otherArray.data.enter();
const ScopedLockType lock1 (getLock());
const ScopedLockType lock2 (otherArray.getLock());
data.swapWith (otherArray.data);
swapVariables (numUsed, otherArray.numUsed);
otherArray.data.exit();
data.exit();
}
/** Adds elements from another array to the end of this array.
@@ -603,8 +548,8 @@ public:
int startIndex = 0,
int numElementsToAdd = -1)
{
arrayToAddFrom.lockArray();
data.enter();
const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
const ScopedLockType lock2 (getLock());
if (startIndex < 0)
{
@@ -617,9 +562,6 @@ public:
while (--numElementsToAdd >= 0)
add (arrayToAddFrom.getUnchecked (startIndex++));
data.exit();
arrayToAddFrom.unlockArray();
}
/** Inserts a new element into the array, assuming that the array is sorted.
@@ -636,9 +578,8 @@ public:
template <class ElementComparator>
void addSorted (ElementComparator& comparator, const ElementType& newElement)
{
data.enter();
const ScopedLockType lock (getLock());
insert (findInsertIndexInSortedArray (comparator, (ElementType*) data.elements, newElement, 0, numUsed), newElement);
data.exit();
}
/** Finds the index of an element in the array, assuming that the array is sorted.
@@ -658,8 +599,8 @@ public:
{
(void) comparator; // if you pass in an object with a static compareElements() method, this
// avoids getting warning messages about the parameter being unused
data.enter();
const ScopedLockType lock (getLock());
int start = 0;
int end = numUsed;
@@ -667,12 +608,10 @@ public:
{
if (start >= end)
{
data.exit();
return -1;
}
else if (comparator.compareElements (elementToLookFor, data.elements [start]) == 0)
{
data.exit();
return start;
}
else
@@ -680,10 +619,7 @@ public:
const int halfway = (start + end) >> 1;
if (halfway == start)
{
data.exit();
return -1;
}
else if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0)
start = halfway;
else
@@ -705,7 +641,7 @@ public:
*/
ElementType remove (const int indexToRemove)
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) indexToRemove) < (unsigned int) numUsed)
{
@@ -722,12 +658,10 @@ public:
if ((numUsed << 1) < data.numAllocated)
minimiseStorageOverheads();
data.exit();
return removed;
}
else
{
data.exit();
return ElementType();
}
}
@@ -742,7 +676,7 @@ public:
*/
void removeValue (const ElementType& valueToRemove)
{
data.enter();
const ScopedLockType lock (getLock());
ElementType* e = data.elements;
for (int i = numUsed; --i >= 0;)
@@ -755,8 +689,6 @@ public:
++e;
}
data.exit();
}
/** Removes a range of elements from the array.
@@ -773,7 +705,7 @@ public:
*/
void removeRange (int startIndex, int numberToRemove)
{
data.enter();
const ScopedLockType lock (getLock());
const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
startIndex = jlimit (0, numUsed, startIndex);
@@ -794,8 +726,6 @@ public:
if ((numUsed << 1) < data.numAllocated)
minimiseStorageOverheads();
}
data.exit();
}
/** Removes the last n elements from the array.
@@ -805,7 +735,7 @@ public:
*/
void removeLast (int howManyToRemove = 1)
{
data.enter();
const ScopedLockType lock (getLock());
if (howManyToRemove > numUsed)
howManyToRemove = numUsed;
@@ -817,8 +747,6 @@ public:
if ((numUsed << 1) < data.numAllocated)
minimiseStorageOverheads();
data.exit();
}
/** Removes any elements which are also in another array.
@@ -829,8 +757,8 @@ public:
template <class OtherArrayType>
void removeValuesIn (const OtherArrayType& otherArray)
{
otherArray.lockArray();
data.enter();
const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
const ScopedLockType lock2 (getLock());
if (this == &otherArray)
{
@@ -845,9 +773,6 @@ public:
remove (i);
}
}
data.exit();
otherArray.unlockArray();
}
/** Removes any elements which are not found in another array.
@@ -860,8 +785,8 @@ public:
template <class OtherArrayType>
void removeValuesNotIn (const OtherArrayType& otherArray)
{
otherArray.lockArray();
data.enter();
const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
const ScopedLockType lock2 (getLock());
if (this != &otherArray)
{
@@ -876,9 +801,6 @@ public:
remove (i);
}
}
data.exit();
otherArray.unlockArray();
}
/** Swaps over two elements in the array.
@@ -892,7 +814,7 @@ public:
void swap (const int index1,
const int index2)
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) index1) < (unsigned int) numUsed
&& ((unsigned int) index2) < (unsigned int) numUsed)
@@ -900,8 +822,6 @@ public:
swapVariables (data.elements [index1],
data.elements [index2]);
}
data.exit();
}
/** Moves one of the values to a different position.
@@ -922,7 +842,7 @@ public:
{
if (currentIndex != newIndex)
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) currentIndex) < (unsigned int) numUsed)
{
@@ -947,8 +867,6 @@ public:
memcpy (data.elements + newIndex, tempCopy, sizeof (ElementType));
}
data.exit();
}
}
@@ -961,9 +879,8 @@ public:
*/
void minimiseStorageOverheads()
{
data.enter();
const ScopedLockType lock (getLock());
data.shrinkToNoMoreThan (numUsed);
data.exit();
}
/** Increases the array's internal storage to hold a minimum number of elements.
@@ -974,9 +891,8 @@ public:
*/
void ensureStorageAllocated (const int minNumElements)
{
data.enter();
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (minNumElements);
data.exit();
}
//==============================================================================
@@ -1010,38 +926,21 @@ public:
void sort (ElementComparator& comparator,
const bool retainOrderOfEquivalentItems = false) const
{
const ScopedLockType lock (getLock());
(void) comparator; // if you pass in an object with a static compareElements() method, this
// avoids getting warning messages about the parameter being unused
data.enter();
sortArray (comparator, (ElementType*) data.elements, 0, size() - 1, retainOrderOfEquivalentItems);
data.exit();
}
//==============================================================================
/** Locks the array's CriticalSection.
Of course if the type of section used is a DummyCriticalSection, this won't
have any effect.
@see unlockArray
/** Returns the CriticalSection that locks this array.
To lock, you can call getLock().enter() and getLock().exit(), or preferably use
an object of ScopedLockType as an RAII lock for it.
*/
void lockArray() const throw()
{
data.enter();
}
/** Unlocks the array's CriticalSection.
Of course if the type of section used is a DummyCriticalSection, this won't
have any effect.
@see lockArray
*/
void unlockArray() const throw()
{
data.exit();
}
inline const TypeOfCriticalSectionToUse& getLock() const throw() { return data; }
/** Returns the type of scoped lock to use for locking this array */
typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
//==============================================================================
juce_UseDebuggingNewOperator


+ 41
- 110
src/containers/juce_OwnedArray.h View File

@@ -78,7 +78,7 @@ public:
/** Clears the array, optionally deleting the objects inside it first. */
void clear (const bool deleteObjects = true)
{
data.enter();
const ScopedLockType lock (getLock());
if (deleteObjects)
{
@@ -88,7 +88,6 @@ public:
data.setAllocatedSize (0);
numUsed = 0;
data.exit();
}
//==============================================================================
@@ -110,13 +109,9 @@ public:
*/
inline ObjectClass* operator[] (const int index) const throw()
{
data.enter();
ObjectClass* const result = (((unsigned int) index) < (unsigned int) numUsed)
? data.elements [index]
: (ObjectClass*) 0;
data.exit();
return result;
const ScopedLockType lock (getLock());
return (((unsigned int) index) < (unsigned int) numUsed) ? data.elements [index]
: (ObjectClass*) 0;
}
/** Returns a pointer to the object at this index in the array, without checking whether the index is in-range.
@@ -126,12 +121,9 @@ public:
*/
inline ObjectClass* getUnchecked (const int index) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
jassert (((unsigned int) index) < (unsigned int) numUsed);
ObjectClass* const result = data.elements [index];
data.exit();
return result;
return data.elements [index];
}
/** Returns a pointer to the first object in the array.
@@ -141,11 +133,9 @@ public:
*/
inline ObjectClass* getFirst() const throw()
{
data.enter();
ObjectClass* const result = (numUsed > 0) ? data.elements [0]
: (ObjectClass*) 0;
data.exit();
return result;
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [0]
: (ObjectClass*) 0;
}
/** Returns a pointer to the last object in the array.
@@ -155,12 +145,9 @@ public:
*/
inline ObjectClass* getLast() const throw()
{
data.enter();
ObjectClass* const result = (numUsed > 0) ? data.elements [numUsed - 1]
: (ObjectClass*) 0;
data.exit();
return result;
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [numUsed - 1]
: (ObjectClass*) 0;
}
//==============================================================================
@@ -171,24 +158,18 @@ public:
*/
int indexOf (const ObjectClass* const objectToLookFor) const throw()
{
int result = -1;
data.enter();
const ScopedLockType lock (getLock());
ObjectClass* const* e = data.elements;
for (int i = numUsed; --i >= 0;)
{
if (objectToLookFor == *e)
{
result = (int) (e - data.elements);
break;
}
return (int) (e - data.elements);
++e;
}
data.exit();
return result;
return -1;
}
/** Returns true if the array contains a specified object.
@@ -198,8 +179,7 @@ public:
*/
bool contains (const ObjectClass* const objectToLookFor) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
ObjectClass* const* e = data.elements;
int i = numUsed;
@@ -210,7 +190,6 @@ public:
|| objectToLookFor == *++e
|| objectToLookFor == *++e)
{
data.exit();
return true;
}
@@ -221,16 +200,12 @@ public:
while (i > 0)
{
if (objectToLookFor == *e)
{
data.exit();
return true;
}
--i;
++e;
}
data.exit();
return false;
}
@@ -248,10 +223,9 @@ public:
*/
void add (const ObjectClass* const newObject) throw()
{
data.enter();
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + 1);
data.elements [numUsed++] = const_cast <ObjectClass*> (newObject);
data.exit();
}
/** Inserts a new object into the array at the given index.
@@ -276,7 +250,7 @@ public:
{
if (indexToInsertAt >= 0)
{
data.enter();
const ScopedLockType lock (getLock());
if (indexToInsertAt > numUsed)
indexToInsertAt = numUsed;
@@ -291,8 +265,6 @@ public:
*e = const_cast <ObjectClass*> (newObject);
++numUsed;
data.exit();
}
else
{
@@ -309,12 +281,10 @@ public:
*/
void addIfNotAlreadyThere (const ObjectClass* const newObject) throw()
{
data.enter();
const ScopedLockType lock (getLock());
if (! contains (newObject))
add (newObject);
data.exit();
}
/** Replaces an object in the array with a different one.
@@ -337,7 +307,7 @@ public:
if (indexToChange >= 0)
{
ScopedPointer <ObjectClass> toDelete;
data.enter();
const ScopedLockType lock (getLock());
if (indexToChange < numUsed)
{
@@ -356,8 +326,6 @@ public:
data.ensureAllocatedSize (numUsed + 1);
data.elements [numUsed++] = const_cast <ObjectClass*> (newObject);
}
data.exit();
}
}
@@ -378,9 +346,8 @@ public:
{
(void) comparator; // if you pass in an object with a static compareElements() method, this
// avoids getting warning messages about the parameter being unused
data.enter();
const ScopedLockType lock (getLock());
insert (findInsertIndexInSortedArray (comparator, (ObjectClass**) data.elements, newObject, 0, numUsed), newObject);
data.exit();
}
/** Finds the index of an object in the array, assuming that the array is sorted.
@@ -401,7 +368,7 @@ public:
{
(void) comparator; // if you pass in an object with a static compareElements() method, this
// avoids getting warning messages about the parameter being unused
data.enter();
const ScopedLockType lock (getLock());
int start = 0;
int end = numUsed;
@@ -410,12 +377,10 @@ public:
{
if (start >= end)
{
data.exit();
return -1;
}
else if (comparator.compareElements (objectToLookFor, data.elements [start]) == 0)
{
data.exit();
return start;
}
else
@@ -423,10 +388,7 @@ public:
const int halfway = (start + end) >> 1;
if (halfway == start)
{
data.exit();
return -1;
}
else if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0)
start = halfway;
else
@@ -450,7 +412,7 @@ public:
const bool deleteObject = true)
{
ScopedPointer <ObjectClass> toDelete;
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) indexToRemove) < (unsigned int) numUsed)
{
@@ -468,8 +430,6 @@ public:
if ((numUsed << 1) < data.numAllocated)
minimiseStorageOverheads();
}
data.exit();
}
/** Removes a specified object from the array.
@@ -483,7 +443,7 @@ public:
void removeObject (const ObjectClass* const objectToRemove,
const bool deleteObject = true)
{
data.enter();
const ScopedLockType lock (getLock());
ObjectClass** e = data.elements;
for (int i = numUsed; --i >= 0;)
@@ -496,8 +456,6 @@ public:
++e;
}
data.exit();
}
/** Removes a range of objects from the array.
@@ -517,7 +475,7 @@ public:
const int numberToRemove,
const bool deleteObjects = true)
{
data.enter();
const ScopedLockType lock (getLock());
const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
startIndex = jlimit (0, numUsed, startIndex);
@@ -546,8 +504,6 @@ public:
if ((numUsed << 1) < data.numAllocated)
minimiseStorageOverheads();
}
data.exit();
}
/** Removes the last n objects from the array.
@@ -559,7 +515,7 @@ public:
void removeLast (int howManyToRemove = 1,
const bool deleteObjects = true)
{
data.enter();
const ScopedLockType lock (getLock());
if (howManyToRemove >= numUsed)
{
@@ -570,8 +526,6 @@ public:
while (--howManyToRemove >= 0)
remove (numUsed - 1, deleteObjects);
}
data.exit();
}
/** Swaps a pair of objects in the array.
@@ -582,7 +536,7 @@ public:
void swap (const int index1,
const int index2) throw()
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) index1) < (unsigned int) numUsed
&& ((unsigned int) index2) < (unsigned int) numUsed)
@@ -590,8 +544,6 @@ public:
swapVariables (data.elements [index1],
data.elements [index2]);
}
data.exit();
}
/** Moves one of the objects to a different position.
@@ -612,7 +564,7 @@ public:
{
if (currentIndex != newIndex)
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) currentIndex) < (unsigned int) numUsed)
{
@@ -636,8 +588,6 @@ public:
data.elements [newIndex] = value;
}
data.exit();
}
}
@@ -646,14 +596,13 @@ public:
If you need to exchange two arrays, this is vastly quicker than using copy-by-value
because it just swaps their internal pointers.
*/
void swapWithArray (OwnedArray <ObjectClass>& otherArray) throw()
void swapWithArray (OwnedArray& otherArray) throw()
{
data.enter();
otherArray.data.enter();
const ScopedLockType lock1 (getLock());
const ScopedLockType lock2 (otherArray.getLock());
data.swapWith (otherArray.data);
swapVariables (numUsed, otherArray.numUsed);
otherArray.data.exit();
data.exit();
}
//==============================================================================
@@ -665,9 +614,8 @@ public:
*/
void minimiseStorageOverheads() throw()
{
data.enter();
const ScopedLockType lock (getLock());
data.shrinkToNoMoreThan (numUsed);
data.exit();
}
/** Increases the array's internal storage to hold a minimum number of elements.
@@ -678,9 +626,8 @@ public:
*/
void ensureStorageAllocated (const int minNumElements) throw()
{
data.enter();
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (minNumElements);
data.exit();
}
//==============================================================================
@@ -716,35 +663,19 @@ public:
(void) comparator; // if you pass in an object with a static compareElements() method, this
// avoids getting warning messages about the parameter being unused
data.enter();
const ScopedLockType lock (getLock());
sortArray (comparator, (ObjectClass**) data.elements, 0, size() - 1, retainOrderOfEquivalentItems);
data.exit();
}
//==============================================================================
/** Locks the array's CriticalSection.
Of course if the type of section used is a DummyCriticalSection, this won't
have any effect.
@see unlockArray
/** Returns the CriticalSection that locks this array.
To lock, you can call getLock().enter() and getLock().exit(), or preferably use
an object of ScopedLockType as an RAII lock for it.
*/
void lockArray() const throw()
{
data.enter();
}
/** Unlocks the array's CriticalSection.
Of course if the type of section used is a DummyCriticalSection, this won't
have any effect.
inline const TypeOfCriticalSectionToUse& getLock() const throw() { return data; }
@see lockArray
*/
void unlockArray() const throw()
{
data.exit();
}
/** Returns the type of scoped lock to use for locking this array */
typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
//==============================================================================


+ 51
- 127
src/containers/juce_ReferenceCountedArray.h View File

@@ -61,7 +61,7 @@ public:
/** Creates a copy of another array */
ReferenceCountedArray (const ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& other) throw()
{
other.lockArray();
const ScopedLockType lock (other.getLock());
numUsed = other.numUsed;
data.setAllocatedSize (numUsed);
memcpy (data.elements, other.data.elements, numUsed * sizeof (ObjectClass*));
@@ -69,8 +69,6 @@ public:
for (int i = numUsed; --i >= 0;)
if (data.elements[i] != 0)
data.elements[i]->incReferenceCount();
other.unlockArray();
}
/** Copies another array into this one.
@@ -104,7 +102,7 @@ public:
*/
void clear()
{
data.enter();
const ScopedLockType lock (getLock());
while (numUsed > 0)
if (data.elements [--numUsed] != 0)
@@ -112,8 +110,6 @@ public:
jassert (numUsed == 0);
data.setAllocatedSize (0);
data.exit();
}
/** Returns the current number of objects in the array. */
@@ -132,12 +128,9 @@ public:
*/
inline const ReferenceCountedObjectPtr<ObjectClass> operator[] (const int index) const throw()
{
data.enter();
const ReferenceCountedObjectPtr<ObjectClass> result ((((unsigned int) index) < (unsigned int) numUsed)
? data.elements [index]
: (ObjectClass*) 0);
data.exit();
return result;
const ScopedLockType lock (getLock());
return (((unsigned int) index) < (unsigned int) numUsed) ? data.elements [index]
: (ObjectClass*) 0;
}
/** Returns a pointer to the object at this index in the array, without checking whether the index is in-range.
@@ -147,11 +140,9 @@ public:
*/
inline const ReferenceCountedObjectPtr<ObjectClass> getUnchecked (const int index) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
jassert (((unsigned int) index) < (unsigned int) numUsed);
const ReferenceCountedObjectPtr<ObjectClass> result (data.elements [index]);
data.exit();
return result;
return data.elements [index];
}
/** Returns a pointer to the first object in the array.
@@ -161,12 +152,9 @@ public:
*/
inline const ReferenceCountedObjectPtr<ObjectClass> getFirst() const throw()
{
data.enter();
const ReferenceCountedObjectPtr<ObjectClass> result ((numUsed > 0) ? data.elements [0]
: (ObjectClass*) 0);
data.exit();
return result;
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [0]
: (ObjectClass*) 0;
}
/** Returns a pointer to the last object in the array.
@@ -176,12 +164,9 @@ public:
*/
inline const ReferenceCountedObjectPtr<ObjectClass> getLast() const throw()
{
data.enter();
const ReferenceCountedObjectPtr<ObjectClass> result ((numUsed > 0) ? data.elements [numUsed - 1]
: (ObjectClass*) 0);
data.exit();
return result;
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [numUsed - 1]
: (ObjectClass*) 0;
}
//==============================================================================
@@ -192,24 +177,18 @@ public:
*/
int indexOf (const ObjectClass* const objectToLookFor) const throw()
{
int result = -1;
data.enter();
const ScopedLockType lock (getLock());
ObjectClass** e = data.elements;
for (int i = numUsed; --i >= 0;)
{
if (objectToLookFor == *e)
{
result = (int) (e - data.elements);
break;
}
return (int) (e - data.elements);
++e;
}
data.exit();
return result;
return -1;
}
/** Returns true if the array contains a specified object.
@@ -219,21 +198,17 @@ public:
*/
bool contains (const ObjectClass* const objectToLookFor) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
ObjectClass** e = data.elements;
for (int i = numUsed; --i >= 0;)
{
if (objectToLookFor == *e)
{
data.exit();
return true;
}
++e;
}
data.exit();
return false;
}
@@ -246,14 +221,12 @@ public:
*/
void add (ObjectClass* const newObject) throw()
{
data.enter();
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + 1);
data.elements [numUsed++] = newObject;
if (newObject != 0)
newObject->incReferenceCount();
data.exit();
}
/** Inserts a new object into the array at the given index.
@@ -274,7 +247,7 @@ public:
{
if (indexToInsertAt >= 0)
{
data.enter();
const ScopedLockType lock (getLock());
if (indexToInsertAt > numUsed)
indexToInsertAt = numUsed;
@@ -293,7 +266,6 @@ public:
newObject->incReferenceCount();
++numUsed;
data.exit();
}
else
{
@@ -310,12 +282,9 @@ public:
*/
void addIfNotAlreadyThere (ObjectClass* const newObject) throw()
{
data.enter();
const ScopedLockType lock (getLock());
if (! contains (newObject))
add (newObject);
data.exit();
}
/** Replaces an object in the array with a different one.
@@ -335,7 +304,7 @@ public:
{
if (indexToChange >= 0)
{
data.enter();
const ScopedLockType lock (getLock());
if (newObject != 0)
newObject->incReferenceCount();
@@ -352,8 +321,6 @@ public:
data.ensureAllocatedSize (numUsed + 1);
data.elements [numUsed++] = newObject;
}
data.exit();
}
}
@@ -371,7 +338,7 @@ public:
int numElementsToAdd = -1) throw()
{
arrayToAddFrom.lockArray();
data.enter();
const ScopedLockType lock (getLock());
if (startIndex < 0)
{
@@ -390,7 +357,6 @@ public:
add (arrayToAddFrom.getUnchecked (startIndex++));
}
data.exit();
arrayToAddFrom.unlockArray();
}
@@ -409,9 +375,8 @@ public:
void addSorted (ElementComparator& comparator,
ObjectClass* newObject) throw()
{
data.enter();
const ScopedLockType lock (getLock());
insert (findInsertIndexInSortedArray (comparator, (ObjectClass**) data.elements, newObject, 0, numUsed), newObject);
data.exit();
}
/** Inserts or replaces an object in the array, assuming it is sorted.
@@ -423,15 +388,13 @@ public:
void addOrReplaceSorted (ElementComparator& comparator,
ObjectClass* newObject) throw()
{
data.enter();
const ScopedLockType lock (getLock());
const int index = findInsertIndexInSortedArray (comparator, (ObjectClass**) data.elements, newObject, 0, numUsed);
if (index > 0 && comparator.compareElements (newObject, data.elements [index - 1]) == 0)
set (index - 1, newObject); // replace an existing object that matches
else
insert (index, newObject); // no match, so insert the new one
data.exit();
}
//==============================================================================
@@ -450,7 +413,7 @@ public:
*/
void remove (const int indexToRemove)
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) indexToRemove) < (unsigned int) numUsed)
{
@@ -468,8 +431,6 @@ public:
if ((numUsed << 1) < data.numAllocated)
minimiseStorageOverheads();
}
data.exit();
}
/** Removes the first occurrence of a specified object from the array.
@@ -482,9 +443,8 @@ public:
*/
void removeObject (ObjectClass* const objectToRemove)
{
data.enter();
const ScopedLockType lock (getLock());
remove (indexOf (objectToRemove));
data.exit();
}
/** Removes a range of objects from the array.
@@ -505,7 +465,7 @@ public:
void removeRange (const int startIndex,
const int numberToRemove)
{
data.enter();
const ScopedLockType lock (getLock());
const int start = jlimit (0, numUsed, startIndex);
const int end = jlimit (0, numUsed, startIndex + numberToRemove);
@@ -536,8 +496,6 @@ public:
if ((numUsed << 1) < data.numAllocated)
minimiseStorageOverheads();
}
data.exit();
}
/** Removes the last n objects from the array.
@@ -550,15 +508,13 @@ public:
*/
void removeLast (int howManyToRemove = 1)
{
data.enter();
const ScopedLockType lock (getLock());
if (howManyToRemove > numUsed)
howManyToRemove = numUsed;
while (--howManyToRemove >= 0)
remove (numUsed - 1);
data.exit();
}
/** Swaps a pair of objects in the array.
@@ -569,7 +525,7 @@ public:
void swap (const int index1,
const int index2) throw()
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) index1) < (unsigned int) numUsed
&& ((unsigned int) index2) < (unsigned int) numUsed)
@@ -577,8 +533,6 @@ public:
swapVariables (data.elements [index1],
data.elements [index2]);
}
data.exit();
}
/** Moves one of the objects to a different position.
@@ -599,7 +553,7 @@ public:
{
if (currentIndex != newIndex)
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) currentIndex) < (unsigned int) numUsed)
{
@@ -623,8 +577,6 @@ public:
data.elements [newIndex] = value;
}
data.exit();
}
}
@@ -634,14 +586,13 @@ public:
If you need to exchange two arrays, this is vastly quicker than using copy-by-value
because it just swaps their internal pointers.
*/
void swapWithArray (ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& otherArray) throw()
void swapWithArray (ReferenceCountedArray& otherArray) throw()
{
data.enter();
otherArray.data.enter();
const ScopedLockType lock1 (getLock());
const ScopedLockType lock2 (otherArray.getLock());
data.swapWith (otherArray.data);
swapVariables (numUsed, otherArray.numUsed);
otherArray.data.exit();
data.exit();
}
//==============================================================================
@@ -649,29 +600,19 @@ public:
@returns true only if the other array contains the same objects in the same order
*/
bool operator== (const ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& other) const throw()
bool operator== (const ReferenceCountedArray& other) const throw()
{
other.lockArray();
data.enter();
const ScopedLockType lock2 (other.getLock());
const ScopedLockType lock1 (getLock());
bool result = numUsed == other.numUsed;
if (numUsed != other.numUsed)
return false;
if (result)
{
for (int i = numUsed; --i >= 0;)
{
if (data.elements [i] != other.data.elements [i])
{
result = false;
break;
}
}
}
data.exit();
other.unlockArray();
for (int i = numUsed; --i >= 0;)
if (data.elements [i] != other.data.elements [i])
return false;
return result;
return true;
}
/** Compares this array to another one.
@@ -717,9 +658,8 @@ public:
(void) comparator; // if you pass in an object with a static compareElements() method, this
// avoids getting warning messages about the parameter being unused
data.enter();
const ScopedLockType lock (getLock());
sortArray (comparator, (ObjectClass**) data.elements, 0, size() - 1, retainOrderOfEquivalentItems);
data.exit();
}
//==============================================================================
@@ -731,35 +671,19 @@ public:
*/
void minimiseStorageOverheads() throw()
{
data.enter();
const ScopedLockType lock (getLock());
data.shrinkToNoMoreThan (numUsed);
data.exit();
}
//==============================================================================
/** Locks the array's CriticalSection.
Of course if the type of section used is a DummyCriticalSection, this won't
have any effect.
@see unlockArray
/** Returns the CriticalSection that locks this array.
To lock, you can call getLock().enter() and getLock().exit(), or preferably use
an object of ScopedLockType as an RAII lock for it.
*/
void lockArray() const throw()
{
data.enter();
}
/** Unlocks the array's CriticalSection.
inline const TypeOfCriticalSectionToUse& getLock() const throw() { return data; }
Of course if the type of section used is a DummyCriticalSection, this won't
have any effect.
@see lockArray
*/
void unlockArray() const throw()
{
data.exit();
}
/** Returns the type of scoped lock to use for locking this array */
typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
//==============================================================================


+ 39
- 113
src/containers/juce_SortedSet.h View File

@@ -71,13 +71,12 @@ public:
/** Creates a copy of another set.
@param other the set to copy
*/
SortedSet (const SortedSet<ElementType, TypeOfCriticalSectionToUse>& other) throw()
SortedSet (const SortedSet& other) throw()
{
other.lockSet();
const ScopedLockType lock (other.getLock());
numUsed = other.numUsed;
data.setAllocatedSize (other.numUsed);
memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType));
other.unlockSet();
}
/** Destructor. */
@@ -88,20 +87,17 @@ public:
/** Copies another set over this one.
@param other the set to copy
*/
SortedSet <ElementType, TypeOfCriticalSectionToUse>& operator= (const SortedSet <ElementType, TypeOfCriticalSectionToUse>& other) throw()
SortedSet& operator= (const SortedSet& other) throw()
{
if (this != &other)
{
other.lockSet();
data.enter();
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.exit();
other.unlockSet();
}
return *this;
@@ -117,24 +113,15 @@ public:
*/
bool operator== (const SortedSet<ElementType>& other) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
if (numUsed != other.numUsed)
{
data.exit();
return false;
}
for (int i = numUsed; --i >= 0;)
{
if (data.elements [i] != other.data.elements [i])
{
data.exit();
if (data.elements[i] != other.data.elements[i])
return false;
}
}
data.exit();
return true;
}
@@ -161,10 +148,9 @@ public:
*/
void clear() throw()
{
data.enter();
const ScopedLockType lock (getLock());
data.setAllocatedSize (0);
numUsed = 0;
data.exit();
}
/** Removes all elements from the set without freeing the array's allocated storage.
@@ -173,9 +159,8 @@ public:
*/
void clearQuick() throw()
{
data.enter();
const ScopedLockType lock (getLock());
numUsed = 0;
data.exit();
}
//==============================================================================
@@ -199,13 +184,9 @@ public:
*/
inline ElementType operator[] (const int index) const throw()
{
data.enter();
const ElementType result = (((unsigned int) index) < (unsigned int) numUsed)
? data.elements [index]
: (ElementType) 0;
data.exit();
return result;
const ScopedLockType lock (getLock());
return (((unsigned int) index) < (unsigned int) numUsed) ? data.elements [index]
: ElementType();
}
/** Returns one of the elements in the set, without checking the index passed in.
@@ -218,12 +199,9 @@ public:
*/
inline ElementType getUnchecked (const int index) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
jassert (((unsigned int) index) < (unsigned int) numUsed);
const ElementType result = data.elements [index];
data.exit();
return result;
return data.elements [index];
}
/** Returns the first element in the set, or 0 if the set is empty.
@@ -232,12 +210,8 @@ public:
*/
inline ElementType getFirst() const throw()
{
data.enter();
const ElementType result = (numUsed > 0) ? data.elements [0]
: (ElementType) 0;
data.exit();
return result;
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [0] : ElementType();
}
/** Returns the last element in the set, or 0 if the set is empty.
@@ -246,12 +220,8 @@ public:
*/
inline ElementType getLast() const throw()
{
data.enter();
const ElementType result = (numUsed > 0) ? data.elements [numUsed - 1]
: (ElementType) 0;
data.exit();
return result;
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [numUsed - 1] : ElementType();
}
//==============================================================================
@@ -265,7 +235,7 @@ public:
*/
int indexOf (const ElementType elementToLookFor) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
int start = 0;
int end = numUsed;
@@ -274,12 +244,10 @@ public:
{
if (start >= end)
{
data.exit();
return -1;
}
else if (elementToLookFor == data.elements [start])
{
data.exit();
return start;
}
else
@@ -287,10 +255,7 @@ public:
const int halfway = (start + end) >> 1;
if (halfway == start)
{
data.exit();
return -1;
}
else if (elementToLookFor >= data.elements [halfway])
start = halfway;
else
@@ -306,7 +271,7 @@ public:
*/
bool contains (const ElementType elementToLookFor) const throw()
{
data.enter();
const ScopedLockType lock (getLock());
int start = 0;
int end = numUsed;
@@ -315,12 +280,10 @@ public:
{
if (start >= end)
{
data.exit();
return false;
}
else if (elementToLookFor == data.elements [start])
{
data.exit();
return true;
}
else
@@ -328,10 +291,7 @@ public:
const int halfway = (start + end) >> 1;
if (halfway == start)
{
data.exit();
return false;
}
else if (elementToLookFor >= data.elements [halfway])
start = halfway;
else
@@ -348,7 +308,7 @@ public:
*/
void add (const ElementType newElement) throw()
{
data.enter();
const ScopedLockType lock (getLock());
int start = 0;
int end = numUsed;
@@ -384,8 +344,6 @@ public:
end = halfway;
}
}
data.exit();
}
/** Adds elements from an array to this set.
@@ -397,12 +355,10 @@ public:
void addArray (const ElementType* elementsToAdd,
int numElementsToAdd) throw()
{
data.enter();
const ScopedLockType lock (getLock());
while (--numElementsToAdd >= 0)
add (*elementsToAdd++);
data.exit();
}
/** Adds elements from another set to this one.
@@ -419,8 +375,8 @@ public:
int startIndex = 0,
int numElementsToAdd = -1) throw()
{
setToAddFrom.lockSet();
data.enter();
const typename OtherSetType::ScopedLockType lock1 (setToAddFrom.getLock());
const ScopedLockType lock2 (getLock());
jassert (this != &setToAddFrom);
if (this != &setToAddFrom)
@@ -436,9 +392,6 @@ public:
addArray (setToAddFrom.elements + startIndex, numElementsToAdd);
}
data.exit();
setToAddFrom.unlockSet();
}
@@ -454,7 +407,7 @@ public:
*/
ElementType remove (const int indexToRemove) throw()
{
data.enter();
const ScopedLockType lock (getLock());
if (((unsigned int) indexToRemove) < (unsigned int) numUsed)
{
@@ -470,14 +423,10 @@ public:
if ((numUsed << 1) < data.numAllocated)
minimiseStorageOverheads();
data.exit();
return removed;
}
else
{
data.exit();
return 0;
}
return 0;
}
/** Removes an item from the set.
@@ -489,9 +438,8 @@ public:
*/
void removeValue (const ElementType valueToRemove) throw()
{
data.enter();
const ScopedLockType lock (getLock());
remove (indexOf (valueToRemove));
data.exit();
}
/** Removes any elements which are also in another set.
@@ -502,8 +450,8 @@ public:
template <class OtherSetType>
void removeValuesIn (const OtherSetType& otherSet) throw()
{
otherSet.lockSet();
data.enter();
const typename OtherSetType::ScopedLockType lock1 (otherSet.getLock());
const ScopedLockType lock2 (getLock());
if (this == &otherSet)
{
@@ -518,9 +466,6 @@ public:
remove (i);
}
}
data.exit();
otherSet.unlockSet();
}
/** Removes any elements which are not found in another set.
@@ -533,8 +478,8 @@ public:
template <class OtherSetType>
void removeValuesNotIn (const OtherSetType& otherSet) throw()
{
otherSet.lockSet();
data.enter();
const typename OtherSetType::ScopedLockType lock1 (otherSet.getLock());
const ScopedLockType lock2 (getLock());
if (this != &otherSet)
{
@@ -549,9 +494,6 @@ public:
remove (i);
}
}
data.exit();
otherSet.lockSet();
}
//==============================================================================
@@ -563,35 +505,19 @@ public:
*/
void minimiseStorageOverheads() throw()
{
data.enter();
const ScopedLockType lock (getLock());
data.shrinkToNoMoreThan (numUsed);
data.exit();
}
//==============================================================================
/** Locks the set's CriticalSection.
Of course if the type of section used is a DummyCriticalSection, this won't
have any effect.
@see unlockSet
/** Returns the CriticalSection that locks this array.
To lock, you can call getLock().enter() and getLock().exit(), or preferably use
an object of ScopedLockType as an RAII lock for it.
*/
void lockSet() const throw()
{
data.enter();
}
/** Unlocks the set's CriticalSection.
inline const TypeOfCriticalSectionToUse& getLock() const throw() { return data; }
Of course if the type of section used is a DummyCriticalSection, this won't
have any effect.
@see lockSet
*/
void unlockSet() const throw()
{
data.exit();
}
/** Returns the type of scoped lock to use for locking this array */
typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
//==============================================================================


+ 37
- 33
src/events/juce_MessageManager.cpp View File

@@ -229,28 +229,27 @@ bool MessageManager::currentThreadHasLockedMessageManager() const throw()
accessed from another thread inside a MM lock, you're screwed. (this is exactly what happens
in Cocoa).
*/
class SharedLockingEvents : public ReferenceCountedObject
class MessageManagerLock::SharedEvents : public ReferenceCountedObject
{
public:
SharedLockingEvents() throw() {}
~SharedLockingEvents() {}
SharedEvents() {}
~SharedEvents() {}
/* This class just holds a couple of events to communicate between the MMLockMessage
/* This class just holds a couple of events to communicate between the BlockingMessage
and the MessageManagerLock. Because both of these objects may be deleted at any time,
this shared data must be kept in a separate, ref-counted container. */
WaitableEvent lockedEvent, releaseEvent;
private:
SharedEvents (const SharedEvents&);
SharedEvents& operator= (const SharedEvents&);
};
class MMLockMessage : public CallbackMessage
class MessageManagerLock::BlockingMessage : public CallbackMessage
{
public:
MMLockMessage (SharedLockingEvents* const events_) throw()
: events (events_)
{}
~MMLockMessage() throw() {}
ReferenceCountedObjectPtr <SharedLockingEvents> events;
BlockingMessage (MessageManagerLock::SharedEvents* const events_) : events (events_) {}
~BlockingMessage() throw() {}
void messageCallback()
{
@@ -260,21 +259,24 @@ public:
juce_UseDebuggingNewOperator
MMLockMessage (const MMLockMessage&);
const MMLockMessage& operator= (const MMLockMessage&);
private:
ReferenceCountedObjectPtr <MessageManagerLock::SharedEvents> events;
BlockingMessage (const BlockingMessage&);
BlockingMessage& operator= (const BlockingMessage&);
};
//==============================================================================
MessageManagerLock::MessageManagerLock (Thread* const threadToCheck) throw()
: locked (false),
needsUnlocking (false)
: sharedEvents (0),
locked (false)
{
init (threadToCheck, 0);
}
MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw()
: locked (false),
needsUnlocking (false)
: sharedEvents (0),
locked (false)
{
init (0, jobToCheckForExitSignal);
}
@@ -305,19 +307,19 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const
}
}
SharedLockingEvents* const events = new SharedLockingEvents();
sharedEvents = events;
events->incReferenceCount();
sharedEvents = new SharedEvents();
sharedEvents->incReferenceCount();
(new MMLockMessage (events))->post();
(new BlockingMessage (sharedEvents))->post();
while (! events->lockedEvent.wait (50))
while (! sharedEvents->lockedEvent.wait (50))
{
if ((threadToCheck != 0 && threadToCheck->threadShouldExit())
|| (job != 0 && job->shouldExit()))
{
events->releaseEvent.signal();
events->decReferenceCount();
sharedEvents->releaseEvent.signal();
sharedEvents->decReferenceCount();
sharedEvents = 0;
MessageManager::instance->lockingLock.exit();
return;
}
@@ -327,22 +329,24 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const
MessageManager::instance->threadWithLock = Thread::getCurrentThreadId();
locked = true;
needsUnlocking = true;
}
}
}
MessageManagerLock::~MessageManagerLock() throw()
{
if (needsUnlocking && MessageManager::instance != 0)
if (sharedEvents != 0)
{
jassert (MessageManager::instance->currentThreadHasLockedMessageManager());
jassert (MessageManager::instance == 0 || MessageManager::instance->currentThreadHasLockedMessageManager());
sharedEvents->releaseEvent.signal();
sharedEvents->decReferenceCount();
((SharedLockingEvents*) sharedEvents)->releaseEvent.signal();
((SharedLockingEvents*) sharedEvents)->decReferenceCount();
MessageManager::instance->threadWithLock = 0;
MessageManager::instance->lockingLock.exit();
if (MessageManager::instance != 0)
{
MessageManager::instance->threadWithLock = 0;
MessageManager::instance->lockingLock.exit();
}
}
}


+ 5
- 3
src/events/juce_MessageManager.h View File

@@ -305,13 +305,15 @@ public:
private:
bool locked, needsUnlocking;
void* sharedEvents;
class SharedEvents;
class BlockingMessage;
SharedEvents* sharedEvents;
bool locked;
void init (Thread* const thread, ThreadPoolJob* const job) throw();
MessageManagerLock (const MessageManagerLock&);
const MessageManagerLock& operator= (const MessageManagerLock&);
MessageManagerLock& operator= (const MessageManagerLock&);
};


+ 9
- 5
src/events/juce_Timer.cpp View File

@@ -79,11 +79,15 @@ public:
const int elapsed = now - lastTime;
lastTime = now;
lock.enter();
decrementAllCounters (elapsed);
const int timeUntilFirstTimer = (firstTimer != 0) ? firstTimer->countdownMs
: 1000;
lock.exit();
int timeUntilFirstTimer = 1000;
{
const ScopedLock sl (lock);
decrementAllCounters (elapsed);
if (firstTimer != 0)
timeUntilFirstTimer = firstTimer->countdownMs;
}
if (timeUntilFirstTimer <= 0)
{


+ 9
- 6
src/gui/components/controls/juce_TreeView.cpp View File

@@ -1168,16 +1168,19 @@ void TreeViewItem::addSubItem (TreeViewItem* const newItem, const int insertPosi
void TreeViewItem::removeSubItem (const int index, const bool deleteItem)
{
if (ownerView != 0)
ownerView->nodeAlterationLock.enter();
{
const ScopedLock sl (ownerView->nodeAlterationLock);
if (((unsigned int) index) < (unsigned int) subItems.size())
if (((unsigned int) index) < (unsigned int) subItems.size())
{
subItems.remove (index, deleteItem);
treeHasChanged();
}
}
else
{
subItems.remove (index, deleteItem);
treeHasChanged();
}
if (ownerView != 0)
ownerView->nodeAlterationLock.exit();
}
bool TreeViewItem::isOpen() const throw()


+ 3
- 5
src/io/streams/juce_OutputStream.cpp View File

@@ -29,7 +29,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_OutputStream.h"
#include "../../threads/juce_CriticalSection.h"
#include "../../threads/juce_ScopedLock.h"
#include "../../containers/juce_VoidArray.h"
@@ -54,18 +54,16 @@ void juce_CheckForDanglingStreams()
OutputStream::OutputStream() throw()
{
#if JUCE_DEBUG
activeStreamLock.enter();
const ScopedLock sl (activeStreamLock);
activeStreams.add (this);
activeStreamLock.exit();
#endif
}
OutputStream::~OutputStream()
{
#if JUCE_DEBUG
activeStreamLock.enter();
const ScopedLock sl (activeStreamLock);
activeStreams.removeValue (this);
activeStreamLock.exit();
#endif
}


+ 8
- 6
src/native/mac/juce_iphone_Audio.cpp View File

@@ -205,9 +205,8 @@ public:
if (callback_ != 0)
callback_->audioDeviceAboutToStart (this);
callbackLock.enter();
const ScopedLock sl (callbackLock);
callback = callback_;
callbackLock.exit();
}
}
@@ -215,10 +214,13 @@ public:
{
if (isRunning)
{
callbackLock.enter();
AudioIODeviceCallback* const lastCallback = callback;
callback = 0;
callbackLock.exit();
AudioIODeviceCallback* lastCallback;
{
const ScopedLock sl (callbackLock);
lastCallback = callback;
callback = 0;
}
if (lastCallback != 0)
lastCallback->audioDeviceStopped();


+ 6
- 7
src/native/mac/juce_mac_CoreAudio.cpp View File

@@ -538,9 +538,10 @@ public:
void stop (bool leaveInterruptRunning)
{
callbackLock.enter();
callback = 0;
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
callback = 0;
}
if (started
&& (deviceID != 0)
@@ -556,8 +557,7 @@ public:
#endif
started = false;
callbackLock.enter();
callbackLock.exit();
{ const ScopedLock sl (callbackLock); }
// wait until it's definately stopped calling back..
for (int i = 40; --i >= 0;)
@@ -578,8 +578,7 @@ public:
break;
}
callbackLock.enter();
callbackLock.exit();
const ScopedLock sl (callbackLock);
}
if (inputDevice != 0)


+ 6
- 7
src/native/mac/juce_mac_CoreMidi.cpp View File

@@ -624,9 +624,10 @@ MidiInput::~MidiInput()
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
mpc->active = false;
callbackLock.enter();
activeCallbacks.removeValue (mpc);
callbackLock.exit();
{
const ScopedLock sl (callbackLock);
activeCallbacks.removeValue (mpc);
}
if (mpc->portAndEndpoint->port != 0)
OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint));
@@ -637,16 +638,14 @@ MidiInput::~MidiInput()
void MidiInput::start()
{
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
const ScopedLock sl (callbackLock);
mpc->active = true;
((MidiPortAndCallback*) internal)->active = true;
}
void MidiInput::stop()
{
MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal;
const ScopedLock sl (callbackLock);
mpc->active = false;
((MidiPortAndCallback*) internal)->active = false;
}
#undef log


+ 41
- 38
src/native/windows/juce_win32_Midi.cpp View File

@@ -82,24 +82,25 @@ public:
return;
const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte);
const double time = timeStampToTime (timeStamp);
lock.enter();
if (pendingLength < midiBufferSize - 12)
{
char* const p = pending + pendingLength;
*(double*) p = time;
*(uint32*) (p + 8) = numBytes;
*(uint32*) (p + 12) = message;
pendingLength += 12 + numBytes;
}
else
{
jassertfalse // midi buffer overflow! You might need to increase the size..
const ScopedLock sl (lock);
if (pendingLength < midiBufferSize - 12)
{
char* const p = pending + pendingLength;
*(double*) p = time;
*(uint32*) (p + 8) = numBytes;
*(uint32*) (p + 12) = message;
pendingLength += 12 + numBytes;
}
else
{
jassertfalse // midi buffer overflow! You might need to increase the size..
}
}
lock.exit();
notify();
}
@@ -111,22 +112,23 @@ public:
{
const double time = timeStampToTime (timeStamp);
lock.enter();
if (pendingLength < midiBufferSize - (8 + num))
{
char* const p = pending + pendingLength;
*(double*) p = time;
*(uint32*) (p + 8) = num;
memcpy (p + 12, hdr->lpData, num);
pendingLength += 12 + num;
}
else
{
jassertfalse // midi buffer overflow! You might need to increase the size..
const ScopedLock sl (lock);
if (pendingLength < midiBufferSize - (8 + num))
{
char* const p = pending + pendingLength;
*(double*) p = time;
*(uint32*) (p + 8) = num;
memcpy (p + 12, hdr->lpData, num);
pendingLength += 12 + num;
}
else
{
jassertfalse // midi buffer overflow! You might need to increase the size..
}
}
lock.exit();
notify();
}
}
@@ -157,20 +159,22 @@ public:
}
}
lock.enter();
int len = pendingLength;
int len;
if (len > 0)
{
pendingCopy.ensureSize (len);
pendingCopy.copyFrom (pending, 0, len);
pendingLength = 0;
}
const ScopedLock sl (lock);
lock.exit();
len = pendingLength;
if (len > 0)
{
pendingCopy.ensureSize (len);
pendingCopy.copyFrom (pending, 0, len);
pendingLength = 0;
}
}
//xxx needs to figure out if blocks are broken up or not
//xxx needs to figure out if blocks are broken up or not
if (len == 0)
{
@@ -234,8 +238,7 @@ public:
activeMidiThreads.removeValue (this);
lock.enter();
lock.exit();
{ const ScopedLock sl (lock); }
for (int i = numInHeaders; --i >= 0;)
{


+ 22
- 2
src/threads/juce_CriticalSection.h View File

@@ -26,6 +26,9 @@
#ifndef __JUCE_CRITICALSECTION_JUCEHEADER__
#define __JUCE_CRITICALSECTION_JUCEHEADER__
class JUCE_API ScopedLock;
class JUCE_API ScopedUnlock;
//==============================================================================
/**
@@ -84,6 +87,13 @@ public:
void exit() const throw();
//==============================================================================
/** Provides the type of scoped lock to use with this type of critical section object. */
typedef ScopedLock ScopedLockType;
/** Provides the type of scoped unlocker to use with this type of critical section object. */
typedef ScopedUnlock ScopedUnlockType;
//==============================================================================
juce_UseDebuggingNewOperator
@@ -103,7 +113,7 @@ private:
#endif
CriticalSection (const CriticalSection&);
const CriticalSection& operator= (const CriticalSection&);
CriticalSection& operator= (const CriticalSection&);
};
@@ -111,7 +121,7 @@ private:
/**
A class that can be used in place of a real CriticalSection object.
This is currently used by some templated array classes, and should get
This is currently used by some templated classes, and should get
optimised out by the compiler.
@see Array, OwnedArray, ReferenceCountedArray
@@ -124,6 +134,16 @@ public:
inline void enter() const throw() {}
inline void exit() const throw() {}
//==============================================================================
/** A dummy scoped-lock type to use with a dummy critical section. */
struct ScopedLockType
{
ScopedLockType (const DummyCriticalSection&) throw() {}
};
/** A dummy scoped-unlocker type to use with a dummy critical section. */
typedef ScopedLockType ScopedUnlockType;
};


+ 14
- 11
src/threads/juce_Thread.cpp View File

@@ -31,7 +31,6 @@ BEGIN_JUCE_NAMESPACE
#include "juce_Thread.h"
#include "juce_ScopedLock.h"
#include "../core/juce_Time.h"
#include "../containers/juce_VoidArray.h"
// these functions are implemented in the platform-specific code.
void* juce_createThread (void* userData);
@@ -42,9 +41,6 @@ void juce_setCurrentThreadName (const String& name);
void juce_CloseThreadHandle (void* handle);
#endif
//==============================================================================
static VoidArray runningThreads;
static CriticalSection runningThreadsLock;
//==============================================================================
void Thread::threadEntryPoint (Thread* const thread)
@@ -251,7 +247,7 @@ Thread* Thread::getCurrentThread()
for (int i = runningThreads.size(); --i >= 0;)
{
Thread* const t = (Thread*) runningThreads.getUnchecked(i);
Thread* const t = runningThreads.getUnchecked(i);
if (t->threadId_ == thisId)
return t;
@@ -266,20 +262,27 @@ void Thread::stopAllThreads (const int timeOutMilliseconds)
const ScopedLock sl (runningThreadsLock);
for (int i = runningThreads.size(); --i >= 0;)
((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit();
runningThreads.getUnchecked(i)->signalThreadShouldExit();
}
for (;;)
{
runningThreadsLock.enter();
Thread* const t = (Thread*) runningThreads[0];
runningThreadsLock.exit();
Thread* firstThread;
{
const ScopedLock sl (runningThreadsLock);
firstThread = runningThreads.getFirst();
}
if (t == 0)
if (firstThread == 0)
break;
t->stopThread (timeOutMilliseconds);
firstThread->stopThread (timeOutMilliseconds);
}
}
Array<Thread*> Thread::runningThreads;
CriticalSection Thread::runningThreadsLock;
END_JUCE_NAMESPACE

+ 3
- 0
src/threads/juce_Thread.h View File

@@ -28,6 +28,7 @@
#include "juce_WaitableEvent.h"
#include "juce_CriticalSection.h"
#include "../containers/juce_Array.h"
//==============================================================================
@@ -281,6 +282,8 @@ private:
friend void JUCE_API juce_threadEntryPoint (void*);
static void threadEntryPoint (Thread* thread);
static Array<Thread*> runningThreads;
static CriticalSection runningThreadsLock;
Thread (const Thread&);
const Thread& operator= (const Thread&);


+ 5
- 7
src/threads/juce_ThreadPool.cpp View File

@@ -221,9 +221,11 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job,
const bool interruptIfRunning,
const int timeOutMs)
{
bool dontWait = true;
if (job != 0)
{
lock.enter();
const ScopedLock sl (lock);
if (jobs.contains (job))
{
@@ -232,20 +234,16 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job,
if (interruptIfRunning)
job->signalJobShouldExit();
lock.exit();
return waitForJobToFinish (job, timeOutMs);
dontWait = false;
}
else
{
jobs.removeValue (job);
}
}
lock.exit();
}
return true;
return dontWait || waitForJobToFinish (job, timeOutMs);
}
bool ThreadPool::removeAllJobs (const bool interruptRunningJobs,


+ 6
- 3
src/utilities/juce_DeletedAtShutdown.cpp View File

@@ -54,9 +54,12 @@ void DeletedAtShutdown::deleteAll()
{
// make a local copy of the array, so it can't get into a loop if something
// creates another DeletedAtShutdown object during its destructor.
lock.enter();
const VoidArray localCopy (objectsToDelete);
lock.exit();
VoidArray localCopy;
{
const ScopedLock sl (lock);
localCopy = objectsToDelete;
}
for (int i = localCopy.size(); --i >= 0;)
{


Loading…
Cancel
Save