diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index a6a67bbf6f..26755cd52b 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -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::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 oldSound (testSound); - audioCallbackLock.exit(); + { // cunningly nested to swap, unlock and delete in that order. + ScopedPointer 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 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 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 diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 7432399cbe..c58a1c9fb9 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -1862,6 +1862,9 @@ public: #ifndef __JUCE_CRITICALSECTION_JUCEHEADER__ #define __JUCE_CRITICALSECTION_JUCEHEADER__ +class JUCE_API ScopedLock; +class JUCE_API ScopedUnlock; + class JUCE_API CriticalSection { public: @@ -1876,6 +1879,10 @@ public: void exit() const throw(); + typedef ScopedLock ScopedLockType; + + typedef ScopedUnlock ScopedUnlockType; + juce_UseDebuggingNewOperator private: @@ -1894,7 +1901,7 @@ private: #endif CriticalSection (const CriticalSection&); - const CriticalSection& operator= (const CriticalSection&); + CriticalSection& operator= (const CriticalSection&); }; class JUCE_API DummyCriticalSection @@ -1905,6 +1912,13 @@ public: inline void enter() const throw() {} inline void exit() const throw() {} + + struct ScopedLockType + { + ScopedLockType (const DummyCriticalSection&) throw() {} + }; + + typedef ScopedLockType ScopedUnlockType; }; #endif // __JUCE_CRITICALSECTION_JUCEHEADER__ @@ -1923,14 +1937,12 @@ public: Array (const Array& 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(); } explicit Array (const ElementType* values) @@ -1955,7 +1967,7 @@ public: data.elements[i].~ElementType(); } - Array & operator= (const Array & other) + Array& operator= (const Array& other) { if (this != &other) { @@ -1969,24 +1981,15 @@ public: template 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; } @@ -1998,25 +2001,23 @@ 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(); } void clearQuick() { - data.enter(); + const ScopedLockType lock (getLock()); for (int i = 0; i < numUsed; ++i) data.elements[i].~ElementType(); numUsed = 0; - data.exit(); } inline int size() const throw() @@ -2026,110 +2027,83 @@ 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(); } 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]; } 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]; } 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(); } 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(); } 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; } 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; } void add (const ElementType& newElement) { - data.enter(); + const ScopedLockType lock (getLock()); data.ensureAllocatedSize (numUsed + 1); new (data.elements + numUsed++) ElementType (newElement); - data.exit(); } void insert (int indexToInsertAt, const ElementType& newElement) { - data.enter(); + const ScopedLockType lock (getLock()); data.ensureAllocatedSize (numUsed + 1); if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) @@ -2147,8 +2121,6 @@ public: { new (data.elements + numUsed++) ElementType (newElement); } - - data.exit(); } void insertMultiple (int indexToInsertAt, const ElementType& newElement, @@ -2156,7 +2128,7 @@ public: { if (numberOfTimesToInsertIt > 0) { - data.enter(); + const ScopedLockType lock (getLock()); data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt); ElementType* insertPos; @@ -2175,8 +2147,6 @@ public: while (--numberOfTimesToInsertIt >= 0) new (insertPos++) ElementType (newElement); - - data.exit(); } } @@ -2186,7 +2156,7 @@ public: { if (numberOfElements > 0) { - data.enter(); + const ScopedLockType lock (getLock()); data.ensureAllocatedSize (numUsed + numberOfElements); ElementType* insertPos; @@ -2205,26 +2175,21 @@ public: while (--numberOfElements >= 0) new (insertPos++) ElementType (*newElements++); - - data.exit(); } } void addIfNotAlreadyThere (const ElementType& newElement) { - data.enter(); + const ScopedLockType lock (getLock()); if (! contains (newElement)) add (newElement); - - data.exit(); } void set (const int indexToChange, const ElementType& newValue) { jassert (indexToChange >= 0); - - data.enter(); + const ScopedLockType lock (getLock()); if (((unsigned int) indexToChange) < (unsigned int) numUsed) { @@ -2235,21 +2200,18 @@ public: data.ensureAllocatedSize (numUsed + 1); new (data.elements + numUsed++) ElementType (newValue); } - - data.exit(); } 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(); } void addArray (const ElementType* elementsToAdd, int numElementsToAdd) { - data.enter(); + const ScopedLockType lock (getLock()); if (numElementsToAdd > 0) { @@ -2258,18 +2220,15 @@ public: while (--numElementsToAdd >= 0) new (data.elements + numUsed++) ElementType (*elementsToAdd++); } - - data.exit(); } - void swapWithArray (Array & 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(); } template @@ -2277,8 +2236,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) { @@ -2291,17 +2250,13 @@ public: while (--numElementsToAdd >= 0) add (arrayToAddFrom.getUnchecked (startIndex++)); - - data.exit(); - arrayToAddFrom.unlockArray(); } template 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(); } template @@ -2309,8 +2264,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; @@ -2318,12 +2273,10 @@ public: { if (start >= end) { - data.exit(); return -1; } else if (comparator.compareElements (elementToLookFor, data.elements [start]) == 0) { - data.exit(); return start; } else @@ -2331,10 +2284,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 @@ -2345,7 +2295,7 @@ public: ElementType remove (const int indexToRemove) { - data.enter(); + const ScopedLockType lock (getLock()); if (((unsigned int) indexToRemove) < (unsigned int) numUsed) { @@ -2362,19 +2312,17 @@ public: if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); - data.exit(); return removed; } else { - data.exit(); return ElementType(); } } void removeValue (const ElementType& valueToRemove) { - data.enter(); + const ScopedLockType lock (getLock()); ElementType* e = data.elements; for (int i = numUsed; --i >= 0;) @@ -2387,13 +2335,11 @@ public: ++e; } - - data.exit(); } 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); @@ -2414,13 +2360,11 @@ public: if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); } - - data.exit(); } void removeLast (int howManyToRemove = 1) { - data.enter(); + const ScopedLockType lock (getLock()); if (howManyToRemove > numUsed) howManyToRemove = numUsed; @@ -2432,15 +2376,13 @@ public: if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); - - data.exit(); } template void removeValuesIn (const OtherArrayType& otherArray) { - otherArray.lockArray(); - data.enter(); + const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock()); + const ScopedLockType lock2 (getLock()); if (this == &otherArray) { @@ -2455,16 +2397,13 @@ public: remove (i); } } - - data.exit(); - otherArray.unlockArray(); } template void removeValuesNotIn (const OtherArrayType& otherArray) { - otherArray.lockArray(); - data.enter(); + const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock()); + const ScopedLockType lock2 (getLock()); if (this != &otherArray) { @@ -2479,15 +2418,12 @@ public: remove (i); } } - - data.exit(); - otherArray.unlockArray(); } 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) @@ -2495,15 +2431,13 @@ public: swapVariables (data.elements [index1], data.elements [index2]); } - - data.exit(); } void move (const int currentIndex, int newIndex) throw() { if (currentIndex != newIndex) { - data.enter(); + const ScopedLockType lock (getLock()); if (((unsigned int) currentIndex) < (unsigned int) numUsed) { @@ -2528,45 +2462,34 @@ public: memcpy (data.elements + newIndex, tempCopy, sizeof (ElementType)); } - - data.exit(); } } void minimiseStorageOverheads() { - data.enter(); + const ScopedLockType lock (getLock()); data.shrinkToNoMoreThan (numUsed); - data.exit(); } void ensureStorageAllocated (const int minNumElements) { - data.enter(); + const ScopedLockType lock (getLock()); data.ensureAllocatedSize (minNumElements); - data.exit(); } template 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(); } - void lockArray() const throw() - { - data.enter(); - } + inline const TypeOfCriticalSectionToUse& getLock() const throw() { return data; } - void unlockArray() const throw() - { - data.exit(); - } + typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType; juce_UseDebuggingNewOperator @@ -3511,7 +3434,7 @@ public: void clear (const bool deleteObjects = true) { - data.enter(); + const ScopedLockType lock (getLock()); if (deleteObjects) { @@ -3521,7 +3444,6 @@ public: data.setAllocatedSize (0); numUsed = 0; - data.exit(); } inline int size() const throw() @@ -3531,70 +3453,51 @@ 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; } 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]; } 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; } 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; } 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; } bool contains (const ObjectClass* const objectToLookFor) const throw() { - data.enter(); - + const ScopedLockType lock (getLock()); ObjectClass* const* e = data.elements; int i = numUsed; @@ -3605,7 +3508,6 @@ public: || objectToLookFor == *++e || objectToLookFor == *++e) { - data.exit(); return true; } @@ -3616,25 +3518,20 @@ public: while (i > 0) { if (objectToLookFor == *e) - { - data.exit(); return true; - } --i; ++e; } - data.exit(); return false; } void add (const ObjectClass* const newObject) throw() { - data.enter(); + const ScopedLockType lock (getLock()); data.ensureAllocatedSize (numUsed + 1); data.elements [numUsed++] = const_cast (newObject); - data.exit(); } void insert (int indexToInsertAt, @@ -3642,7 +3539,7 @@ public: { if (indexToInsertAt >= 0) { - data.enter(); + const ScopedLockType lock (getLock()); if (indexToInsertAt > numUsed) indexToInsertAt = numUsed; @@ -3657,8 +3554,6 @@ public: *e = const_cast (newObject); ++numUsed; - - data.exit(); } else { @@ -3668,12 +3563,10 @@ public: void addIfNotAlreadyThere (const ObjectClass* const newObject) throw() { - data.enter(); + const ScopedLockType lock (getLock()); if (! contains (newObject)) add (newObject); - - data.exit(); } void set (const int indexToChange, @@ -3683,7 +3576,7 @@ public: if (indexToChange >= 0) { ScopedPointer toDelete; - data.enter(); + const ScopedLockType lock (getLock()); if (indexToChange < numUsed) { @@ -3702,8 +3595,6 @@ public: data.ensureAllocatedSize (numUsed + 1); data.elements [numUsed++] = const_cast (newObject); } - - data.exit(); } } @@ -3713,9 +3604,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(); } template @@ -3724,7 +3614,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; @@ -3733,12 +3623,10 @@ public: { if (start >= end) { - data.exit(); return -1; } else if (comparator.compareElements (objectToLookFor, data.elements [start]) == 0) { - data.exit(); return start; } else @@ -3746,10 +3634,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 @@ -3762,7 +3647,7 @@ public: const bool deleteObject = true) { ScopedPointer toDelete; - data.enter(); + const ScopedLockType lock (getLock()); if (((unsigned int) indexToRemove) < (unsigned int) numUsed) { @@ -3780,14 +3665,12 @@ public: if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); } - - data.exit(); } 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;) @@ -3800,15 +3683,13 @@ public: ++e; } - - data.exit(); } void removeRange (int startIndex, 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); @@ -3837,14 +3718,12 @@ public: if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); } - - data.exit(); } void removeLast (int howManyToRemove = 1, const bool deleteObjects = true) { - data.enter(); + const ScopedLockType lock (getLock()); if (howManyToRemove >= numUsed) { @@ -3855,14 +3734,12 @@ public: while (--howManyToRemove >= 0) remove (numUsed - 1, deleteObjects); } - - data.exit(); } 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) @@ -3870,8 +3747,6 @@ public: swapVariables (data.elements [index1], data.elements [index2]); } - - data.exit(); } void move (const int currentIndex, @@ -3879,7 +3754,7 @@ public: { if (currentIndex != newIndex) { - data.enter(); + const ScopedLockType lock (getLock()); if (((unsigned int) currentIndex) < (unsigned int) numUsed) { @@ -3903,33 +3778,28 @@ public: data.elements [newIndex] = value; } - - data.exit(); } } - void swapWithArray (OwnedArray & 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(); } void minimiseStorageOverheads() throw() { - data.enter(); + const ScopedLockType lock (getLock()); data.shrinkToNoMoreThan (numUsed); - data.exit(); } void ensureStorageAllocated (const int minNumElements) throw() { - data.enter(); + const ScopedLockType lock (getLock()); data.ensureAllocatedSize (minNumElements); - data.exit(); } template @@ -3939,20 +3809,13 @@ 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(); } - void lockArray() const throw() - { - data.enter(); - } + inline const TypeOfCriticalSectionToUse& getLock() const throw() { return data; } - void unlockArray() const throw() - { - data.exit(); - } + typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType; juce_UseDebuggingNewOperator @@ -5013,7 +4876,7 @@ public: ReferenceCountedArray (const ReferenceCountedArray& other) throw() { - other.lockArray(); + const ScopedLockType lock (other.getLock()); numUsed = other.numUsed; data.setAllocatedSize (numUsed); memcpy (data.elements, other.data.elements, numUsed * sizeof (ObjectClass*)); @@ -5021,8 +4884,6 @@ public: for (int i = numUsed; --i >= 0;) if (data.elements[i] != 0) data.elements[i]->incReferenceCount(); - - other.unlockArray(); } ReferenceCountedArray& operator= (const ReferenceCountedArray& other) throw() @@ -5043,7 +4904,7 @@ public: void clear() { - data.enter(); + const ScopedLockType lock (getLock()); while (numUsed > 0) if (data.elements [--numUsed] != 0) @@ -5051,8 +4912,6 @@ public: jassert (numUsed == 0); data.setAllocatedSize (0); - - data.exit(); } inline int size() const throw() @@ -5062,95 +4921,72 @@ public: inline const ReferenceCountedObjectPtr operator[] (const int index) const throw() { - data.enter(); - const ReferenceCountedObjectPtr 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; } inline const ReferenceCountedObjectPtr getUnchecked (const int index) const throw() { - data.enter(); + const ScopedLockType lock (getLock()); jassert (((unsigned int) index) < (unsigned int) numUsed); - const ReferenceCountedObjectPtr result (data.elements [index]); - data.exit(); - return result; + return data.elements [index]; } inline const ReferenceCountedObjectPtr getFirst() const throw() { - data.enter(); - const ReferenceCountedObjectPtr result ((numUsed > 0) ? data.elements [0] - : (ObjectClass*) 0); - data.exit(); - - return result; + const ScopedLockType lock (getLock()); + return numUsed > 0 ? data.elements [0] + : (ObjectClass*) 0; } inline const ReferenceCountedObjectPtr getLast() const throw() { - data.enter(); - const ReferenceCountedObjectPtr 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; } 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; } 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; } 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(); } void insert (int indexToInsertAt, @@ -5158,7 +4994,7 @@ public: { if (indexToInsertAt >= 0) { - data.enter(); + const ScopedLockType lock (getLock()); if (indexToInsertAt > numUsed) indexToInsertAt = numUsed; @@ -5177,7 +5013,6 @@ public: newObject->incReferenceCount(); ++numUsed; - data.exit(); } else { @@ -5187,12 +5022,9 @@ public: void addIfNotAlreadyThere (ObjectClass* const newObject) throw() { - data.enter(); - + const ScopedLockType lock (getLock()); if (! contains (newObject)) add (newObject); - - data.exit(); } void set (const int indexToChange, @@ -5200,7 +5032,7 @@ public: { if (indexToChange >= 0) { - data.enter(); + const ScopedLockType lock (getLock()); if (newObject != 0) newObject->incReferenceCount(); @@ -5217,8 +5049,6 @@ public: data.ensureAllocatedSize (numUsed + 1); data.elements [numUsed++] = newObject; } - - data.exit(); } } @@ -5227,7 +5057,7 @@ public: int numElementsToAdd = -1) throw() { arrayToAddFrom.lockArray(); - data.enter(); + const ScopedLockType lock (getLock()); if (startIndex < 0) { @@ -5246,7 +5076,6 @@ public: add (arrayToAddFrom.getUnchecked (startIndex++)); } - data.exit(); arrayToAddFrom.unlockArray(); } @@ -5254,29 +5083,26 @@ 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(); } template 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(); } void remove (const int indexToRemove) { - data.enter(); + const ScopedLockType lock (getLock()); if (((unsigned int) indexToRemove) < (unsigned int) numUsed) { @@ -5294,21 +5120,18 @@ public: if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); } - - data.exit(); } void removeObject (ObjectClass* const objectToRemove) { - data.enter(); + const ScopedLockType lock (getLock()); remove (indexOf (objectToRemove)); - data.exit(); } 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); @@ -5339,27 +5162,23 @@ public: if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); } - - data.exit(); } void removeLast (int howManyToRemove = 1) { - data.enter(); + const ScopedLockType lock (getLock()); if (howManyToRemove > numUsed) howManyToRemove = numUsed; while (--howManyToRemove >= 0) remove (numUsed - 1); - - data.exit(); } 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) @@ -5367,8 +5186,6 @@ public: swapVariables (data.elements [index1], data.elements [index2]); } - - data.exit(); } void move (const int currentIndex, @@ -5376,7 +5193,7 @@ public: { if (currentIndex != newIndex) { - data.enter(); + const ScopedLockType lock (getLock()); if (((unsigned int) currentIndex) < (unsigned int) numUsed) { @@ -5400,44 +5217,31 @@ public: data.elements [newIndex] = value; } - - data.exit(); } } - void swapWithArray (ReferenceCountedArray& 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(); } - bool operator== (const ReferenceCountedArray& other) const throw() + bool operator== (const ReferenceCountedArray& other) const throw() { - other.lockArray(); - data.enter(); - - bool result = numUsed == other.numUsed; + const ScopedLockType lock2 (other.getLock()); + const ScopedLockType lock1 (getLock()); - if (result) - { - for (int i = numUsed; --i >= 0;) - { - if (data.elements [i] != other.data.elements [i]) - { - result = false; - break; - } - } - } + if (numUsed != other.numUsed) + return false; - data.exit(); - other.unlockArray(); + for (int i = numUsed; --i >= 0;) + if (data.elements [i] != other.data.elements [i]) + return false; - return result; + return true; } bool operator!= (const ReferenceCountedArray& other) const throw() @@ -5452,27 +5256,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(); } void minimiseStorageOverheads() throw() { - data.enter(); + const ScopedLockType lock (getLock()); data.shrinkToNoMoreThan (numUsed); - data.exit(); } - void lockArray() const throw() - { - data.enter(); - } + inline const TypeOfCriticalSectionToUse& getLock() const throw() { return data; } - void unlockArray() const throw() - { - data.exit(); - } + typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType; juce_UseDebuggingNewOperator @@ -5513,33 +5309,29 @@ public: { } - SortedSet (const SortedSet& 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(); } ~SortedSet() throw() { } - SortedSet & operator= (const SortedSet & 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; @@ -5547,24 +5339,15 @@ public: bool operator== (const SortedSet& 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; } @@ -5575,17 +5358,15 @@ public: void clear() throw() { - data.enter(); + const ScopedLockType lock (getLock()); data.setAllocatedSize (0); numUsed = 0; - data.exit(); } void clearQuick() throw() { - data.enter(); + const ScopedLockType lock (getLock()); numUsed = 0; - data.exit(); } inline int size() const throw() @@ -5595,48 +5376,33 @@ 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(); } 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]; } 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(); } 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(); } int indexOf (const ElementType elementToLookFor) const throw() { - data.enter(); + const ScopedLockType lock (getLock()); int start = 0; int end = numUsed; @@ -5645,12 +5411,10 @@ public: { if (start >= end) { - data.exit(); return -1; } else if (elementToLookFor == data.elements [start]) { - data.exit(); return start; } else @@ -5658,10 +5422,7 @@ public: const int halfway = (start + end) >> 1; if (halfway == start) - { - data.exit(); return -1; - } else if (elementToLookFor >= data.elements [halfway]) start = halfway; else @@ -5672,7 +5433,7 @@ public: bool contains (const ElementType elementToLookFor) const throw() { - data.enter(); + const ScopedLockType lock (getLock()); int start = 0; int end = numUsed; @@ -5681,12 +5442,10 @@ public: { if (start >= end) { - data.exit(); return false; } else if (elementToLookFor == data.elements [start]) { - data.exit(); return true; } else @@ -5694,10 +5453,7 @@ public: const int halfway = (start + end) >> 1; if (halfway == start) - { - data.exit(); return false; - } else if (elementToLookFor >= data.elements [halfway]) start = halfway; else @@ -5708,7 +5464,7 @@ public: void add (const ElementType newElement) throw() { - data.enter(); + const ScopedLockType lock (getLock()); int start = 0; int end = numUsed; @@ -5744,19 +5500,15 @@ public: end = halfway; } } - - data.exit(); } void addArray (const ElementType* elementsToAdd, int numElementsToAdd) throw() { - data.enter(); + const ScopedLockType lock (getLock()); while (--numElementsToAdd >= 0) add (*elementsToAdd++); - - data.exit(); } template @@ -5764,8 +5516,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) @@ -5781,14 +5533,11 @@ public: addArray (setToAddFrom.elements + startIndex, numElementsToAdd); } - - data.exit(); - setToAddFrom.unlockSet(); } ElementType remove (const int indexToRemove) throw() { - data.enter(); + const ScopedLockType lock (getLock()); if (((unsigned int) indexToRemove) < (unsigned int) numUsed) { @@ -5804,28 +5553,23 @@ public: if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); - data.exit(); return removed; } - else - { - data.exit(); - return 0; - } + + return 0; } void removeValue (const ElementType valueToRemove) throw() { - data.enter(); + const ScopedLockType lock (getLock()); remove (indexOf (valueToRemove)); - data.exit(); } template void removeValuesIn (const OtherSetType& otherSet) throw() { - otherSet.lockSet(); - data.enter(); + const typename OtherSetType::ScopedLockType lock1 (otherSet.getLock()); + const ScopedLockType lock2 (getLock()); if (this == &otherSet) { @@ -5840,16 +5584,13 @@ public: remove (i); } } - - data.exit(); - otherSet.unlockSet(); } template void removeValuesNotIn (const OtherSetType& otherSet) throw() { - otherSet.lockSet(); - data.enter(); + const typename OtherSetType::ScopedLockType lock1 (otherSet.getLock()); + const ScopedLockType lock2 (getLock()); if (this != &otherSet) { @@ -5864,27 +5605,17 @@ public: remove (i); } } - - data.exit(); - otherSet.lockSet(); } void minimiseStorageOverheads() throw() { - data.enter(); + const ScopedLockType lock (getLock()); data.shrinkToNoMoreThan (numUsed); - data.exit(); } - void lockSet() const throw() - { - data.enter(); - } + inline const TypeOfCriticalSectionToUse& getLock() const throw() { return data; } - void unlockSet() const throw() - { - data.exit(); - } + typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType; juce_UseDebuggingNewOperator @@ -8797,6 +8528,8 @@ private: friend void JUCE_API juce_threadEntryPoint (void*); static void threadEntryPoint (Thread* thread); + static Array runningThreads; + static CriticalSection runningThreadsLock; Thread (const Thread&); const Thread& operator= (const Thread&); @@ -19866,13 +19599,15 @@ public: bool lockWasGained() const throw() { return locked; } 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&); }; #endif // __JUCE_MESSAGEMANAGER_JUCEHEADER__ diff --git a/src/audio/audio_sources/juce_AudioTransportSource.cpp b/src/audio/audio_sources/juce_AudioTransportSource.cpp index ca1633eef2..5a2e7d4da3 100644 --- a/src/audio/audio_sources/juce_AudioTransportSource.cpp +++ b/src/audio/audio_sources/juce_AudioTransportSource.cpp @@ -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) diff --git a/src/audio/audio_sources/juce_BufferingAudioSource.cpp b/src/audio/audio_sources/juce_BufferingAudioSource.cpp index d36324c958..810229d033 100644 --- a/src/audio/audio_sources/juce_BufferingAudioSource.cpp +++ b/src/audio/audio_sources/juce_BufferingAudioSource.cpp @@ -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) { diff --git a/src/audio/audio_sources/juce_MixerAudioSource.cpp b/src/audio/audio_sources/juce_MixerAudioSource.cpp index 76afd2edfc..ee4f844d16 100644 --- a/src/audio/audio_sources/juce_MixerAudioSource.cpp +++ b/src/audio/audio_sources/juce_MixerAudioSource.cpp @@ -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]) diff --git a/src/audio/devices/juce_AudioDeviceManager.cpp b/src/audio/devices/juce_AudioDeviceManager.cpp index 09c1597b34..e0f8a155f3 100644 --- a/src/audio/devices/juce_AudioDeviceManager.cpp +++ b/src/audio/devices/juce_AudioDeviceManager.cpp @@ -919,10 +919,13 @@ void AudioDeviceManager::CallbackHandler::handleIncomingMidiMessage (MidiInput* //============================================================================== void AudioDeviceManager::playTestSound() { - { - audioCallbackLock.enter(); - ScopedPointer oldSound (testSound); - audioCallbackLock.exit(); + { // cunningly nested to swap, unlock and delete in that order. + ScopedPointer oldSound; + + { + const ScopedLock sl (audioCallbackLock); + oldSound = testSound; + } } testSoundPosition = 0; diff --git a/src/audio/devices/juce_MidiOutput.cpp b/src/audio/devices/juce_MidiOutput.cpp index 36d181c8ab..b99c1a6aec 100644 --- a/src/audio/devices/juce_MidiOutput.cpp +++ b/src/audio/devices/juce_MidiOutput.cpp @@ -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) diff --git a/src/audio/processors/juce_AudioProcessor.cpp b/src/audio/processors/juce_AudioProcessor.cpp index c68c6ca324..7fcc1021a8 100644 --- a/src/audio/processors/juce_AudioProcessor.cpp +++ b/src/audio/processors/juce_AudioProcessor.cpp @@ -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); diff --git a/src/audio/processors/juce_AudioProcessorPlayer.cpp b/src/audio/processors/juce_AudioProcessorPlayer.cpp index bf54e3dd8a..e3d1c95d99 100644 --- a/src/audio/processors/juce_AudioProcessorPlayer.cpp +++ b/src/audio/processors/juce_AudioProcessorPlayer.cpp @@ -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(); diff --git a/src/containers/juce_Array.h b/src/containers/juce_Array.h index 82f950a769..4b26a6e5a9 100644 --- a/src/containers/juce_Array.h +++ b/src/containers/juce_Array.h @@ -72,14 +72,12 @@ public: */ Array (const Array& 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 & operator= (const Array & other) + Array& operator= (const Array& other) { if (this != &other) { @@ -137,24 +135,15 @@ public: template 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 & 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 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 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 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 diff --git a/src/containers/juce_OwnedArray.h b/src/containers/juce_OwnedArray.h index 3b44834558..a0ec732f92 100644 --- a/src/containers/juce_OwnedArray.h +++ b/src/containers/juce_OwnedArray.h @@ -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 (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 (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 toDelete; - data.enter(); + const ScopedLockType lock (getLock()); if (indexToChange < numUsed) { @@ -356,8 +326,6 @@ public: data.ensureAllocatedSize (numUsed + 1); data.elements [numUsed++] = const_cast (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 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 & 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; //============================================================================== diff --git a/src/containers/juce_ReferenceCountedArray.h b/src/containers/juce_ReferenceCountedArray.h index 5d2b6ef9f9..a82d9d8899 100644 --- a/src/containers/juce_ReferenceCountedArray.h +++ b/src/containers/juce_ReferenceCountedArray.h @@ -61,7 +61,7 @@ public: /** Creates a copy of another array */ ReferenceCountedArray (const ReferenceCountedArray& 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 operator[] (const int index) const throw() { - data.enter(); - const ReferenceCountedObjectPtr 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 getUnchecked (const int index) const throw() { - data.enter(); + const ScopedLockType lock (getLock()); jassert (((unsigned int) index) < (unsigned int) numUsed); - const ReferenceCountedObjectPtr 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 getFirst() const throw() { - data.enter(); - const ReferenceCountedObjectPtr 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 getLast() const throw() { - data.enter(); - const ReferenceCountedObjectPtr 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& 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& 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; //============================================================================== diff --git a/src/containers/juce_SortedSet.h b/src/containers/juce_SortedSet.h index 1fc8212abe..cc1e1ce895 100644 --- a/src/containers/juce_SortedSet.h +++ b/src/containers/juce_SortedSet.h @@ -71,13 +71,12 @@ public: /** Creates a copy of another set. @param other the set to copy */ - SortedSet (const SortedSet& 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 & operator= (const SortedSet & 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& 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 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 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; //============================================================================== diff --git a/src/events/juce_MessageManager.cpp b/src/events/juce_MessageManager.cpp index fd6ff3a053..b11fb6e788 100644 --- a/src/events/juce_MessageManager.cpp +++ b/src/events/juce_MessageManager.cpp @@ -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 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 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(); + } } } diff --git a/src/events/juce_MessageManager.h b/src/events/juce_MessageManager.h index ed0900fc45..c4307e0ae7 100644 --- a/src/events/juce_MessageManager.h +++ b/src/events/juce_MessageManager.h @@ -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&); }; diff --git a/src/events/juce_Timer.cpp b/src/events/juce_Timer.cpp index 2c301b81a0..fdc55b9468 100644 --- a/src/events/juce_Timer.cpp +++ b/src/events/juce_Timer.cpp @@ -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) { diff --git a/src/gui/components/controls/juce_TreeView.cpp b/src/gui/components/controls/juce_TreeView.cpp index 443dd90eb3..d647b3de14 100644 --- a/src/gui/components/controls/juce_TreeView.cpp +++ b/src/gui/components/controls/juce_TreeView.cpp @@ -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() diff --git a/src/io/streams/juce_OutputStream.cpp b/src/io/streams/juce_OutputStream.cpp index 9c928e1ec6..e0e06815b2 100644 --- a/src/io/streams/juce_OutputStream.cpp +++ b/src/io/streams/juce_OutputStream.cpp @@ -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 } diff --git a/src/native/mac/juce_iphone_Audio.cpp b/src/native/mac/juce_iphone_Audio.cpp index 2c9d578f5e..4c70b078b8 100644 --- a/src/native/mac/juce_iphone_Audio.cpp +++ b/src/native/mac/juce_iphone_Audio.cpp @@ -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(); diff --git a/src/native/mac/juce_mac_CoreAudio.cpp b/src/native/mac/juce_mac_CoreAudio.cpp index 8b6758582f..6fdfaee844 100644 --- a/src/native/mac/juce_mac_CoreAudio.cpp +++ b/src/native/mac/juce_mac_CoreAudio.cpp @@ -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) diff --git a/src/native/mac/juce_mac_CoreMidi.cpp b/src/native/mac/juce_mac_CoreMidi.cpp index 4a9f688bdb..0b43a63c72 100644 --- a/src/native/mac/juce_mac_CoreMidi.cpp +++ b/src/native/mac/juce_mac_CoreMidi.cpp @@ -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 diff --git a/src/native/windows/juce_win32_Midi.cpp b/src/native/windows/juce_win32_Midi.cpp index 52ab8b455f..2343806b0d 100644 --- a/src/native/windows/juce_win32_Midi.cpp +++ b/src/native/windows/juce_win32_Midi.cpp @@ -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;) { diff --git a/src/threads/juce_CriticalSection.h b/src/threads/juce_CriticalSection.h index 3d312d71a4..2fc6ae754e 100644 --- a/src/threads/juce_CriticalSection.h +++ b/src/threads/juce_CriticalSection.h @@ -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; }; diff --git a/src/threads/juce_Thread.cpp b/src/threads/juce_Thread.cpp index a6fe0029c8..adee333de5 100644 --- a/src/threads/juce_Thread.cpp +++ b/src/threads/juce_Thread.cpp @@ -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::runningThreads; +CriticalSection Thread::runningThreadsLock; + + END_JUCE_NAMESPACE diff --git a/src/threads/juce_Thread.h b/src/threads/juce_Thread.h index d59b920a19..7b71c934cc 100644 --- a/src/threads/juce_Thread.h +++ b/src/threads/juce_Thread.h @@ -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 runningThreads; + static CriticalSection runningThreadsLock; Thread (const Thread&); const Thread& operator= (const Thread&); diff --git a/src/threads/juce_ThreadPool.cpp b/src/threads/juce_ThreadPool.cpp index a1dbfde071..8b1d2ba3b0 100644 --- a/src/threads/juce_ThreadPool.cpp +++ b/src/threads/juce_ThreadPool.cpp @@ -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, diff --git a/src/utilities/juce_DeletedAtShutdown.cpp b/src/utilities/juce_DeletedAtShutdown.cpp index 609bead8f2..94de2752b1 100644 --- a/src/utilities/juce_DeletedAtShutdown.cpp +++ b/src/utilities/juce_DeletedAtShutdown.cpp @@ -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;) {