| @@ -5417,18 +5417,16 @@ void juce_CheckForDanglingStreams() | |||||
| OutputStream::OutputStream() throw() | OutputStream::OutputStream() throw() | ||||
| { | { | ||||
| #if JUCE_DEBUG | #if JUCE_DEBUG | ||||
| activeStreamLock.enter(); | |||||
| const ScopedLock sl (activeStreamLock); | |||||
| activeStreams.add (this); | activeStreams.add (this); | ||||
| activeStreamLock.exit(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| OutputStream::~OutputStream() | OutputStream::~OutputStream() | ||||
| { | { | ||||
| #if JUCE_DEBUG | #if JUCE_DEBUG | ||||
| activeStreamLock.enter(); | |||||
| const ScopedLock sl (activeStreamLock); | |||||
| activeStreams.removeValue (this); | activeStreams.removeValue (this); | ||||
| activeStreamLock.exit(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -15373,9 +15371,6 @@ void juce_setCurrentThreadName (const String& name); | |||||
| void juce_CloseThreadHandle (void* handle); | void juce_CloseThreadHandle (void* handle); | ||||
| #endif | #endif | ||||
| static VoidArray runningThreads; | |||||
| static CriticalSection runningThreadsLock; | |||||
| void Thread::threadEntryPoint (Thread* const thread) | void Thread::threadEntryPoint (Thread* const thread) | ||||
| { | { | ||||
| { | { | ||||
| @@ -15573,7 +15568,7 @@ Thread* Thread::getCurrentThread() | |||||
| for (int i = runningThreads.size(); --i >= 0;) | for (int i = runningThreads.size(); --i >= 0;) | ||||
| { | { | ||||
| Thread* const t = (Thread*) runningThreads.getUnchecked(i); | |||||
| Thread* const t = runningThreads.getUnchecked(i); | |||||
| if (t->threadId_ == thisId) | if (t->threadId_ == thisId) | ||||
| return t; | return t; | ||||
| @@ -15588,22 +15583,28 @@ void Thread::stopAllThreads (const int timeOutMilliseconds) | |||||
| const ScopedLock sl (runningThreadsLock); | const ScopedLock sl (runningThreadsLock); | ||||
| for (int i = runningThreads.size(); --i >= 0;) | for (int i = runningThreads.size(); --i >= 0;) | ||||
| ((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit(); | |||||
| runningThreads.getUnchecked(i)->signalThreadShouldExit(); | |||||
| } | } | ||||
| for (;;) | 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; | break; | ||||
| t->stopThread (timeOutMilliseconds); | |||||
| firstThread->stopThread (timeOutMilliseconds); | |||||
| } | } | ||||
| } | } | ||||
| Array<Thread*> Thread::runningThreads; | |||||
| CriticalSection Thread::runningThreadsLock; | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| /*** End of inlined file: juce_Thread.cpp ***/ | /*** End of inlined file: juce_Thread.cpp ***/ | ||||
| @@ -15796,9 +15797,11 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job, | |||||
| const bool interruptIfRunning, | const bool interruptIfRunning, | ||||
| const int timeOutMs) | const int timeOutMs) | ||||
| { | { | ||||
| bool dontWait = true; | |||||
| if (job != 0) | if (job != 0) | ||||
| { | { | ||||
| lock.enter(); | |||||
| const ScopedLock sl (lock); | |||||
| if (jobs.contains (job)) | if (jobs.contains (job)) | ||||
| { | { | ||||
| @@ -15807,20 +15810,16 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job, | |||||
| if (interruptIfRunning) | if (interruptIfRunning) | ||||
| job->signalJobShouldExit(); | job->signalJobShouldExit(); | ||||
| lock.exit(); | |||||
| return waitForJobToFinish (job, timeOutMs); | |||||
| dontWait = false; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| jobs.removeValue (job); | jobs.removeValue (job); | ||||
| } | } | ||||
| } | } | ||||
| lock.exit(); | |||||
| } | } | ||||
| return true; | |||||
| return dontWait || waitForJobToFinish (job, timeOutMs); | |||||
| } | } | ||||
| bool ThreadPool::removeAllJobs (const bool interruptRunningJobs, | 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 | // make a local copy of the array, so it can't get into a loop if something | ||||
| // creates another DeletedAtShutdown object during its destructor. | // 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;) | for (int i = localCopy.size(); --i >= 0;) | ||||
| { | { | ||||
| @@ -22950,11 +22952,12 @@ void AudioTransportSource::start() | |||||
| { | { | ||||
| if ((! playing) && masterSource != 0) | 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); | sendChangeMessage (this); | ||||
| } | } | ||||
| @@ -22964,9 +22967,10 @@ void AudioTransportSource::stop() | |||||
| { | { | ||||
| if (playing) | if (playing) | ||||
| { | { | ||||
| callbackLock.enter(); | |||||
| playing = false; | |||||
| callbackLock.exit(); | |||||
| { | |||||
| const ScopedLock sl (callbackLock); | |||||
| playing = false; | |||||
| } | |||||
| int n = 500; | int n = 500; | ||||
| while (--n >= 0 && ! stopped) | while (--n >= 0 && ! stopped) | ||||
| @@ -23350,45 +23354,47 @@ void BufferingAudioSource::setNextReadPosition (int newPosition) | |||||
| bool BufferingAudioSource::readNextBufferChunk() | 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) | if (sectionToReadStart != sectionToReadEnd) | ||||
| { | { | ||||
| @@ -23696,10 +23702,14 @@ void MixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhen | |||||
| { | { | ||||
| if (input != 0 && ! inputs.contains (input)) | 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) | if (localRate != 0.0) | ||||
| input->prepareToPlay (localBufferSize, localRate); | input->prepareToPlay (localBufferSize, localRate); | ||||
| @@ -23715,16 +23725,19 @@ void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteI | |||||
| { | { | ||||
| if (input != 0) | 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) | if (index >= 0) | ||||
| { | { | ||||
| @@ -23738,11 +23751,14 @@ void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteI | |||||
| void MixerAudioSource::removeAllInputs() | 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;) | for (int i = inputsCopy.size(); --i >= 0;) | ||||
| if (inputsToDeleteCopy[i]) | if (inputsToDeleteCopy[i]) | ||||
| @@ -24987,10 +25003,13 @@ void AudioDeviceManager::CallbackHandler::handleIncomingMidiMessage (MidiInput* | |||||
| void AudioDeviceManager::playTestSound() | void AudioDeviceManager::playTestSound() | ||||
| { | { | ||||
| { | |||||
| audioCallbackLock.enter(); | |||||
| ScopedPointer <AudioSampleBuffer> oldSound (testSound); | |||||
| audioCallbackLock.exit(); | |||||
| { // cunningly nested to swap, unlock and delete in that order. | |||||
| ScopedPointer <AudioSampleBuffer> oldSound; | |||||
| { | |||||
| const ScopedLock sl (audioCallbackLock); | |||||
| oldSound = testSound; | |||||
| } | |||||
| } | } | ||||
| testSoundPosition = 0; | testSoundPosition = 0; | ||||
| @@ -25179,26 +25198,28 @@ void MidiOutput::run() | |||||
| uint32 eventTime = 0; | uint32 eventTime = 0; | ||||
| uint32 timeToWait = 500; | 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 (message != 0) | ||||
| { | { | ||||
| if (eventTime > now) | if (eventTime > now) | ||||
| @@ -34679,9 +34700,12 @@ void AudioProcessor::sendParamChangeMessageToListeners (const int parameterIndex | |||||
| for (int i = listeners.size(); --i >= 0;) | 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) | if (l != 0) | ||||
| l->audioProcessorParameterChanged (this, parameterIndex, newValue); | l->audioProcessorParameterChanged (this, parameterIndex, newValue); | ||||
| @@ -34701,9 +34725,12 @@ void AudioProcessor::beginParameterChangeGesture (int parameterIndex) | |||||
| for (int i = listeners.size(); --i >= 0;) | 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) | if (l != 0) | ||||
| l->audioProcessorParameterChangeGestureBegin (this, parameterIndex); | l->audioProcessorParameterChangeGestureBegin (this, parameterIndex); | ||||
| @@ -34724,9 +34751,12 @@ void AudioProcessor::endParameterChangeGesture (int parameterIndex) | |||||
| for (int i = listeners.size(); --i >= 0;) | 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) | if (l != 0) | ||||
| l->audioProcessorParameterChangeGestureEnd (this, parameterIndex); | l->audioProcessorParameterChangeGestureEnd (this, parameterIndex); | ||||
| @@ -34737,9 +34767,12 @@ void AudioProcessor::updateHostDisplay() | |||||
| { | { | ||||
| for (int i = listeners.size(); --i >= 0;) | 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) | if (l != 0) | ||||
| l->audioProcessorChanged (this); | l->audioProcessorChanged (this); | ||||
| @@ -36211,11 +36244,14 @@ void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay) | |||||
| processorToPlay->prepareToPlay (sampleRate, blockSize); | 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) | if (oldOne != 0) | ||||
| oldOne->releaseResources(); | oldOne->releaseResources(); | ||||
| @@ -37963,25 +37999,24 @@ bool MessageManager::currentThreadHasLockedMessageManager() const throw() | |||||
| return thisThread == messageThreadId || thisThread == threadWithLock; | return thisThread == messageThreadId || thisThread == threadWithLock; | ||||
| } | } | ||||
| class SharedLockingEvents : public ReferenceCountedObject | |||||
| class MessageManagerLock::SharedEvents : public ReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| SharedLockingEvents() throw() {} | |||||
| ~SharedLockingEvents() {} | |||||
| SharedEvents() {} | |||||
| ~SharedEvents() {} | |||||
| WaitableEvent lockedEvent, releaseEvent; | WaitableEvent lockedEvent, releaseEvent; | ||||
| private: | |||||
| SharedEvents (const SharedEvents&); | |||||
| SharedEvents& operator= (const SharedEvents&); | |||||
| }; | }; | ||||
| class MMLockMessage : public CallbackMessage | |||||
| class MessageManagerLock::BlockingMessage : public CallbackMessage | |||||
| { | { | ||||
| public: | public: | ||||
| MMLockMessage (SharedLockingEvents* const events_) throw() | |||||
| : events (events_) | |||||
| {} | |||||
| ~MMLockMessage() throw() {} | |||||
| ReferenceCountedObjectPtr <SharedLockingEvents> events; | |||||
| BlockingMessage (MessageManagerLock::SharedEvents* const events_) : events (events_) {} | |||||
| ~BlockingMessage() throw() {} | |||||
| void messageCallback() | void messageCallback() | ||||
| { | { | ||||
| @@ -37991,20 +38026,23 @@ public: | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| MMLockMessage (const MMLockMessage&); | |||||
| const MMLockMessage& operator= (const MMLockMessage&); | |||||
| private: | |||||
| ReferenceCountedObjectPtr <MessageManagerLock::SharedEvents> events; | |||||
| BlockingMessage (const BlockingMessage&); | |||||
| BlockingMessage& operator= (const BlockingMessage&); | |||||
| }; | }; | ||||
| MessageManagerLock::MessageManagerLock (Thread* const threadToCheck) throw() | MessageManagerLock::MessageManagerLock (Thread* const threadToCheck) throw() | ||||
| : locked (false), | |||||
| needsUnlocking (false) | |||||
| : sharedEvents (0), | |||||
| locked (false) | |||||
| { | { | ||||
| init (threadToCheck, 0); | init (threadToCheck, 0); | ||||
| } | } | ||||
| MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw() | MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw() | ||||
| : locked (false), | |||||
| needsUnlocking (false) | |||||
| : sharedEvents (0), | |||||
| locked (false) | |||||
| { | { | ||||
| init (0, jobToCheckForExitSignal); | 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()) | if ((threadToCheck != 0 && threadToCheck->threadShouldExit()) | ||||
| || (job != 0 && job->shouldExit())) | || (job != 0 && job->shouldExit())) | ||||
| { | { | ||||
| events->releaseEvent.signal(); | |||||
| events->decReferenceCount(); | |||||
| sharedEvents->releaseEvent.signal(); | |||||
| sharedEvents->decReferenceCount(); | |||||
| sharedEvents = 0; | |||||
| MessageManager::instance->lockingLock.exit(); | MessageManager::instance->lockingLock.exit(); | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -38057,21 +38095,24 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const | |||||
| MessageManager::instance->threadWithLock = Thread::getCurrentThreadId(); | MessageManager::instance->threadWithLock = Thread::getCurrentThreadId(); | ||||
| locked = true; | locked = true; | ||||
| needsUnlocking = true; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| MessageManagerLock::~MessageManagerLock() throw() | 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; | const int elapsed = now - lastTime; | ||||
| lastTime = now; | 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) | 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) | void TreeViewItem::removeSubItem (const int index, const bool deleteItem) | ||||
| { | { | ||||
| if (ownerView != 0) | 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); | subItems.remove (index, deleteItem); | ||||
| treeHasChanged(); | |||||
| } | } | ||||
| if (ownerView != 0) | |||||
| ownerView->nodeAlterationLock.exit(); | |||||
| } | } | ||||
| bool TreeViewItem::isOpen() const throw() | bool TreeViewItem::isOpen() const throw() | ||||
| @@ -222335,24 +222383,25 @@ public: | |||||
| return; | return; | ||||
| const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte); | const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte); | ||||
| const double time = timeStampToTime (timeStamp); | 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(); | notify(); | ||||
| } | } | ||||
| @@ -222364,22 +222413,23 @@ public: | |||||
| { | { | ||||
| const double time = timeStampToTime (timeStamp); | 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(); | 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) | if (len == 0) | ||||
| { | { | ||||
| @@ -222487,8 +222539,7 @@ public: | |||||
| activeMidiThreads.removeValue (this); | activeMidiThreads.removeValue (this); | ||||
| lock.enter(); | |||||
| lock.exit(); | |||||
| { const ScopedLock sl (lock); } | |||||
| for (int i = numInHeaders; --i >= 0;) | for (int i = numInHeaders; --i >= 0;) | ||||
| { | { | ||||
| @@ -242981,9 +243032,8 @@ public: | |||||
| if (callback_ != 0) | if (callback_ != 0) | ||||
| callback_->audioDeviceAboutToStart (this); | callback_->audioDeviceAboutToStart (this); | ||||
| callbackLock.enter(); | |||||
| const ScopedLock sl (callbackLock); | |||||
| callback = callback_; | callback = callback_; | ||||
| callbackLock.exit(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -242991,10 +243041,13 @@ public: | |||||
| { | { | ||||
| if (isRunning) | 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) | if (lastCallback != 0) | ||||
| lastCallback->audioDeviceStopped(); | lastCallback->audioDeviceStopped(); | ||||
| @@ -243939,9 +243992,10 @@ MidiInput::~MidiInput() | |||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | ||||
| mpc->active = false; | mpc->active = false; | ||||
| callbackLock.enter(); | |||||
| activeCallbacks.removeValue (mpc); | |||||
| callbackLock.exit(); | |||||
| { | |||||
| const ScopedLock sl (callbackLock); | |||||
| activeCallbacks.removeValue (mpc); | |||||
| } | |||||
| if (mpc->portAndEndpoint->port != 0) | if (mpc->portAndEndpoint->port != 0) | ||||
| OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); | OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); | ||||
| @@ -243952,16 +244006,14 @@ MidiInput::~MidiInput() | |||||
| void MidiInput::start() | void MidiInput::start() | ||||
| { | { | ||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | |||||
| const ScopedLock sl (callbackLock); | const ScopedLock sl (callbackLock); | ||||
| mpc->active = true; | |||||
| ((MidiPortAndCallback*) internal)->active = true; | |||||
| } | } | ||||
| void MidiInput::stop() | void MidiInput::stop() | ||||
| { | { | ||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | |||||
| const ScopedLock sl (callbackLock); | const ScopedLock sl (callbackLock); | ||||
| mpc->active = false; | |||||
| ((MidiPortAndCallback*) internal)->active = false; | |||||
| } | } | ||||
| #undef log | #undef log | ||||
| @@ -250475,9 +250527,10 @@ public: | |||||
| void stop (bool leaveInterruptRunning) | void stop (bool leaveInterruptRunning) | ||||
| { | { | ||||
| callbackLock.enter(); | |||||
| callback = 0; | |||||
| callbackLock.exit(); | |||||
| { | |||||
| const ScopedLock sl (callbackLock); | |||||
| callback = 0; | |||||
| } | |||||
| if (started | if (started | ||||
| && (deviceID != 0) | && (deviceID != 0) | ||||
| @@ -250493,8 +250546,7 @@ public: | |||||
| #endif | #endif | ||||
| started = false; | started = false; | ||||
| callbackLock.enter(); | |||||
| callbackLock.exit(); | |||||
| { const ScopedLock sl (callbackLock); } | |||||
| // wait until it's definately stopped calling back.. | // wait until it's definately stopped calling back.. | ||||
| for (int i = 40; --i >= 0;) | for (int i = 40; --i >= 0;) | ||||
| @@ -250515,8 +250567,7 @@ public: | |||||
| break; | break; | ||||
| } | } | ||||
| callbackLock.enter(); | |||||
| callbackLock.exit(); | |||||
| const ScopedLock sl (callbackLock); | |||||
| } | } | ||||
| if (inputDevice != 0) | if (inputDevice != 0) | ||||
| @@ -251850,9 +251901,10 @@ MidiInput::~MidiInput() | |||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | ||||
| mpc->active = false; | mpc->active = false; | ||||
| callbackLock.enter(); | |||||
| activeCallbacks.removeValue (mpc); | |||||
| callbackLock.exit(); | |||||
| { | |||||
| const ScopedLock sl (callbackLock); | |||||
| activeCallbacks.removeValue (mpc); | |||||
| } | |||||
| if (mpc->portAndEndpoint->port != 0) | if (mpc->portAndEndpoint->port != 0) | ||||
| OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); | OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); | ||||
| @@ -251863,16 +251915,14 @@ MidiInput::~MidiInput() | |||||
| void MidiInput::start() | void MidiInput::start() | ||||
| { | { | ||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | |||||
| const ScopedLock sl (callbackLock); | const ScopedLock sl (callbackLock); | ||||
| mpc->active = true; | |||||
| ((MidiPortAndCallback*) internal)->active = true; | |||||
| } | } | ||||
| void MidiInput::stop() | void MidiInput::stop() | ||||
| { | { | ||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | |||||
| const ScopedLock sl (callbackLock); | const ScopedLock sl (callbackLock); | ||||
| mpc->active = false; | |||||
| ((MidiPortAndCallback*) internal)->active = false; | |||||
| } | } | ||||
| #undef log | #undef log | ||||
| @@ -128,11 +128,12 @@ void AudioTransportSource::start() | |||||
| { | { | ||||
| if ((! playing) && masterSource != 0) | 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); | sendChangeMessage (this); | ||||
| } | } | ||||
| @@ -142,9 +143,10 @@ void AudioTransportSource::stop() | |||||
| { | { | ||||
| if (playing) | if (playing) | ||||
| { | { | ||||
| callbackLock.enter(); | |||||
| playing = false; | |||||
| callbackLock.exit(); | |||||
| { | |||||
| const ScopedLock sl (callbackLock); | |||||
| playing = false; | |||||
| } | |||||
| int n = 500; | int n = 500; | ||||
| while (--n >= 0 && ! stopped) | while (--n >= 0 && ! stopped) | ||||
| @@ -269,45 +269,47 @@ void BufferingAudioSource::setNextReadPosition (int newPosition) | |||||
| bool BufferingAudioSource::readNextBufferChunk() | 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) | if (sectionToReadStart != sectionToReadEnd) | ||||
| { | { | ||||
| @@ -49,10 +49,14 @@ void MixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhen | |||||
| { | { | ||||
| if (input != 0 && ! inputs.contains (input)) | 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) | if (localRate != 0.0) | ||||
| input->prepareToPlay (localBufferSize, localRate); | input->prepareToPlay (localBufferSize, localRate); | ||||
| @@ -68,16 +72,19 @@ void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteI | |||||
| { | { | ||||
| if (input != 0) | 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) | if (index >= 0) | ||||
| { | { | ||||
| @@ -91,11 +98,14 @@ void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteI | |||||
| void MixerAudioSource::removeAllInputs() | 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;) | for (int i = inputsCopy.size(); --i >= 0;) | ||||
| if (inputsToDeleteCopy[i]) | if (inputsToDeleteCopy[i]) | ||||
| @@ -919,10 +919,13 @@ void AudioDeviceManager::CallbackHandler::handleIncomingMidiMessage (MidiInput* | |||||
| //============================================================================== | //============================================================================== | ||||
| void AudioDeviceManager::playTestSound() | void AudioDeviceManager::playTestSound() | ||||
| { | { | ||||
| { | |||||
| audioCallbackLock.enter(); | |||||
| ScopedPointer <AudioSampleBuffer> oldSound (testSound); | |||||
| audioCallbackLock.exit(); | |||||
| { // cunningly nested to swap, unlock and delete in that order. | |||||
| ScopedPointer <AudioSampleBuffer> oldSound; | |||||
| { | |||||
| const ScopedLock sl (audioCallbackLock); | |||||
| oldSound = testSound; | |||||
| } | |||||
| } | } | ||||
| testSoundPosition = 0; | testSoundPosition = 0; | ||||
| @@ -123,26 +123,28 @@ void MidiOutput::run() | |||||
| uint32 eventTime = 0; | uint32 eventTime = 0; | ||||
| uint32 timeToWait = 500; | 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 (message != 0) | ||||
| { | { | ||||
| if (eventTime > now) | if (eventTime > now) | ||||
| @@ -114,9 +114,12 @@ void AudioProcessor::sendParamChangeMessageToListeners (const int parameterIndex | |||||
| for (int i = listeners.size(); --i >= 0;) | 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) | if (l != 0) | ||||
| l->audioProcessorParameterChanged (this, parameterIndex, newValue); | l->audioProcessorParameterChanged (this, parameterIndex, newValue); | ||||
| @@ -136,9 +139,12 @@ void AudioProcessor::beginParameterChangeGesture (int parameterIndex) | |||||
| for (int i = listeners.size(); --i >= 0;) | 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) | if (l != 0) | ||||
| l->audioProcessorParameterChangeGestureBegin (this, parameterIndex); | l->audioProcessorParameterChangeGestureBegin (this, parameterIndex); | ||||
| @@ -159,9 +165,12 @@ void AudioProcessor::endParameterChangeGesture (int parameterIndex) | |||||
| for (int i = listeners.size(); --i >= 0;) | 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) | if (l != 0) | ||||
| l->audioProcessorParameterChangeGestureEnd (this, parameterIndex); | l->audioProcessorParameterChangeGestureEnd (this, parameterIndex); | ||||
| @@ -172,9 +181,12 @@ void AudioProcessor::updateHostDisplay() | |||||
| { | { | ||||
| for (int i = listeners.size(); --i >= 0;) | 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) | if (l != 0) | ||||
| l->audioProcessorChanged (this); | l->audioProcessorChanged (this); | ||||
| @@ -61,11 +61,14 @@ void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay) | |||||
| processorToPlay->prepareToPlay (sampleRate, blockSize); | 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) | if (oldOne != 0) | ||||
| oldOne->releaseResources(); | oldOne->releaseResources(); | ||||
| @@ -72,14 +72,12 @@ public: | |||||
| */ | */ | ||||
| Array (const Array<ElementType, TypeOfCriticalSectionToUse>& other) | Array (const Array<ElementType, TypeOfCriticalSectionToUse>& other) | ||||
| { | { | ||||
| other.lockArray(); | |||||
| const ScopedLockType lock (other.getLock()); | |||||
| numUsed = other.numUsed; | numUsed = other.numUsed; | ||||
| data.setAllocatedSize (other.numUsed); | data.setAllocatedSize (other.numUsed); | ||||
| for (int i = 0; i < numUsed; ++i) | for (int i = 0; i < numUsed; ++i) | ||||
| new (data.elements + i) ElementType (other.data.elements[i]); | new (data.elements + i) ElementType (other.data.elements[i]); | ||||
| other.unlockArray(); | |||||
| } | } | ||||
| /** Initalises from a null-terminated C array of values. | /** Initalises from a null-terminated C array of values. | ||||
| @@ -117,7 +115,7 @@ public: | |||||
| /** Copies another array. | /** Copies another array. | ||||
| @param other the array to copy | @param other the array to copy | ||||
| */ | */ | ||||
| Array <ElementType, TypeOfCriticalSectionToUse>& operator= (const Array <ElementType, TypeOfCriticalSectionToUse>& other) | |||||
| Array& operator= (const Array& other) | |||||
| { | { | ||||
| if (this != &other) | if (this != &other) | ||||
| { | { | ||||
| @@ -137,24 +135,15 @@ public: | |||||
| template <class OtherArrayType> | template <class OtherArrayType> | ||||
| bool operator== (const OtherArrayType& other) const | bool operator== (const OtherArrayType& other) const | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (numUsed != other.numUsed) | if (numUsed != other.numUsed) | ||||
| { | |||||
| data.exit(); | |||||
| return false; | return false; | ||||
| } | |||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| { | |||||
| if (data.elements [i] != other.data.elements [i]) | if (data.elements [i] != other.data.elements [i]) | ||||
| { | |||||
| data.exit(); | |||||
| return false; | return false; | ||||
| } | |||||
| } | |||||
| data.exit(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -179,14 +168,13 @@ public: | |||||
| */ | */ | ||||
| void clear() | void clear() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| for (int i = 0; i < numUsed; ++i) | for (int i = 0; i < numUsed; ++i) | ||||
| data.elements[i].~ElementType(); | data.elements[i].~ElementType(); | ||||
| data.setAllocatedSize (0); | data.setAllocatedSize (0); | ||||
| numUsed = 0; | numUsed = 0; | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes all elements from the array without freeing the array's allocated storage. | /** Removes all elements from the array without freeing the array's allocated storage. | ||||
| @@ -195,13 +183,12 @@ public: | |||||
| */ | */ | ||||
| void clearQuick() | void clearQuick() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| for (int i = 0; i < numUsed; ++i) | for (int i = 0; i < numUsed; ++i) | ||||
| data.elements[i].~ElementType(); | data.elements[i].~ElementType(); | ||||
| numUsed = 0; | numUsed = 0; | ||||
| data.exit(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -224,13 +211,9 @@ public: | |||||
| */ | */ | ||||
| inline ElementType operator[] (const int index) const | 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. | /** 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 | inline const ElementType getUnchecked (const int index) const | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| jassert (((unsigned int) index) < (unsigned int) numUsed); | 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. | /** 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() | inline ElementType& getReference (const int index) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| jassert (((unsigned int) index) < (unsigned int) numUsed); | 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. | /** Returns the first element in the array, or 0 if the array is empty. | ||||
| @@ -276,12 +254,9 @@ public: | |||||
| */ | */ | ||||
| inline ElementType getFirst() const | 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. | /** Returns the last element in the array, or 0 if the array is empty. | ||||
| @@ -290,12 +265,9 @@ public: | |||||
| */ | */ | ||||
| inline ElementType getLast() const | 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 indexOf (const ElementType& elementToLookFor) const | ||||
| { | { | ||||
| int result = -1; | |||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| const ElementType* e = data.elements; | const ElementType* e = data.elements; | ||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| { | { | ||||
| if (elementToLookFor == *e) | if (elementToLookFor == *e) | ||||
| { | |||||
| result = (int) (e - data.elements); | |||||
| break; | |||||
| } | |||||
| return (int) (e - data.elements); | |||||
| ++e; | ++e; | ||||
| } | } | ||||
| data.exit(); | |||||
| return result; | |||||
| return -1; | |||||
| } | } | ||||
| /** Returns true if the array contains at least one occurrence of an object. | /** Returns true if the array contains at least one occurrence of an object. | ||||
| @@ -336,24 +302,19 @@ public: | |||||
| */ | */ | ||||
| bool contains (const ElementType& elementToLookFor) const | bool contains (const ElementType& elementToLookFor) const | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| const ElementType* e = data.elements; | const ElementType* e = data.elements; | ||||
| int num = numUsed; | int num = numUsed; | ||||
| while (num > 0) | while (num > 0) | ||||
| { | { | ||||
| if (elementToLookFor == *e) | if (elementToLookFor == *e) | ||||
| { | |||||
| data.exit(); | |||||
| return true; | return true; | ||||
| } | |||||
| --num; | --num; | ||||
| ++e; | ++e; | ||||
| } | } | ||||
| data.exit(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -365,10 +326,9 @@ public: | |||||
| */ | */ | ||||
| void add (const ElementType& newElement) | void add (const ElementType& newElement) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (numUsed + 1); | data.ensureAllocatedSize (numUsed + 1); | ||||
| new (data.elements + numUsed++) ElementType (newElement); | new (data.elements + numUsed++) ElementType (newElement); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Inserts a new element into the array at a given position. | /** Inserts a new element into the array at a given position. | ||||
| @@ -385,7 +345,7 @@ public: | |||||
| */ | */ | ||||
| void insert (int indexToInsertAt, const ElementType& newElement) | void insert (int indexToInsertAt, const ElementType& newElement) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (numUsed + 1); | data.ensureAllocatedSize (numUsed + 1); | ||||
| if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) | if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) | ||||
| @@ -403,8 +363,6 @@ public: | |||||
| { | { | ||||
| new (data.elements + numUsed++) ElementType (newElement); | new (data.elements + numUsed++) ElementType (newElement); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Inserts multiple copies of an element into the array at a given position. | /** Inserts multiple copies of an element into the array at a given position. | ||||
| @@ -424,7 +382,7 @@ public: | |||||
| { | { | ||||
| if (numberOfTimesToInsertIt > 0) | if (numberOfTimesToInsertIt > 0) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt); | data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt); | ||||
| ElementType* insertPos; | ElementType* insertPos; | ||||
| @@ -443,8 +401,6 @@ public: | |||||
| while (--numberOfTimesToInsertIt >= 0) | while (--numberOfTimesToInsertIt >= 0) | ||||
| new (insertPos++) ElementType (newElement); | new (insertPos++) ElementType (newElement); | ||||
| data.exit(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -466,7 +422,7 @@ public: | |||||
| { | { | ||||
| if (numberOfElements > 0) | if (numberOfElements > 0) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (numUsed + numberOfElements); | data.ensureAllocatedSize (numUsed + numberOfElements); | ||||
| ElementType* insertPos; | ElementType* insertPos; | ||||
| @@ -485,8 +441,6 @@ public: | |||||
| while (--numberOfElements >= 0) | while (--numberOfElements >= 0) | ||||
| new (insertPos++) ElementType (*newElements++); | new (insertPos++) ElementType (*newElements++); | ||||
| data.exit(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -500,12 +454,10 @@ public: | |||||
| */ | */ | ||||
| void addIfNotAlreadyThere (const ElementType& newElement) | void addIfNotAlreadyThere (const ElementType& newElement) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (! contains (newElement)) | if (! contains (newElement)) | ||||
| add (newElement); | add (newElement); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Replaces an element with a new value. | /** Replaces an element with a new value. | ||||
| @@ -520,8 +472,7 @@ public: | |||||
| void set (const int indexToChange, const ElementType& newValue) | void set (const int indexToChange, const ElementType& newValue) | ||||
| { | { | ||||
| jassert (indexToChange >= 0); | jassert (indexToChange >= 0); | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) indexToChange) < (unsigned int) numUsed) | if (((unsigned int) indexToChange) < (unsigned int) numUsed) | ||||
| { | { | ||||
| @@ -532,8 +483,6 @@ public: | |||||
| data.ensureAllocatedSize (numUsed + 1); | data.ensureAllocatedSize (numUsed + 1); | ||||
| new (data.elements + numUsed++) ElementType (newValue); | new (data.elements + numUsed++) ElementType (newValue); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Replaces an element with a new value without doing any bounds-checking. | /** 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) | void setUnchecked (const int indexToChange, const ElementType& newValue) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| jassert (((unsigned int) indexToChange) < (unsigned int) numUsed); | jassert (((unsigned int) indexToChange) < (unsigned int) numUsed); | ||||
| data.elements [indexToChange] = newValue; | data.elements [indexToChange] = newValue; | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Adds elements from an array to the end of this array. | /** Adds elements from an array to the end of this array. | ||||
| @@ -561,7 +509,7 @@ public: | |||||
| */ | */ | ||||
| void addArray (const ElementType* elementsToAdd, int numElementsToAdd) | void addArray (const ElementType* elementsToAdd, int numElementsToAdd) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (numElementsToAdd > 0) | if (numElementsToAdd > 0) | ||||
| { | { | ||||
| @@ -570,8 +518,6 @@ public: | |||||
| while (--numElementsToAdd >= 0) | while (--numElementsToAdd >= 0) | ||||
| new (data.elements + numUsed++) ElementType (*elementsToAdd++); | new (data.elements + numUsed++) ElementType (*elementsToAdd++); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** This swaps the contents of this array with those of another array. | /** 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 | If you need to exchange two arrays, this is vastly quicker than using copy-by-value | ||||
| because it just swaps their internal pointers. | because it just swaps their internal pointers. | ||||
| */ | */ | ||||
| void swapWithArray (Array <ElementType>& otherArray) throw() | |||||
| void swapWithArray (Array& otherArray) throw() | |||||
| { | { | ||||
| data.enter(); | |||||
| otherArray.data.enter(); | |||||
| const ScopedLockType lock1 (getLock()); | |||||
| const ScopedLockType lock2 (otherArray.getLock()); | |||||
| data.swapWith (otherArray.data); | data.swapWith (otherArray.data); | ||||
| swapVariables (numUsed, otherArray.numUsed); | swapVariables (numUsed, otherArray.numUsed); | ||||
| otherArray.data.exit(); | |||||
| data.exit(); | |||||
| } | } | ||||
| /** Adds elements from another array to the end of this array. | /** Adds elements from another array to the end of this array. | ||||
| @@ -603,8 +548,8 @@ public: | |||||
| int startIndex = 0, | int startIndex = 0, | ||||
| int numElementsToAdd = -1) | int numElementsToAdd = -1) | ||||
| { | { | ||||
| arrayToAddFrom.lockArray(); | |||||
| data.enter(); | |||||
| const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock()); | |||||
| const ScopedLockType lock2 (getLock()); | |||||
| if (startIndex < 0) | if (startIndex < 0) | ||||
| { | { | ||||
| @@ -617,9 +562,6 @@ public: | |||||
| while (--numElementsToAdd >= 0) | while (--numElementsToAdd >= 0) | ||||
| add (arrayToAddFrom.getUnchecked (startIndex++)); | add (arrayToAddFrom.getUnchecked (startIndex++)); | ||||
| data.exit(); | |||||
| arrayToAddFrom.unlockArray(); | |||||
| } | } | ||||
| /** Inserts a new element into the array, assuming that the array is sorted. | /** Inserts a new element into the array, assuming that the array is sorted. | ||||
| @@ -636,9 +578,8 @@ public: | |||||
| template <class ElementComparator> | template <class ElementComparator> | ||||
| void addSorted (ElementComparator& comparator, const ElementType& newElement) | void addSorted (ElementComparator& comparator, const ElementType& newElement) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| insert (findInsertIndexInSortedArray (comparator, (ElementType*) data.elements, newElement, 0, numUsed), newElement); | 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. | /** 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 | (void) comparator; // if you pass in an object with a static compareElements() method, this | ||||
| // avoids getting warning messages about the parameter being unused | // avoids getting warning messages about the parameter being unused | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| int start = 0; | int start = 0; | ||||
| int end = numUsed; | int end = numUsed; | ||||
| @@ -667,12 +608,10 @@ public: | |||||
| { | { | ||||
| if (start >= end) | if (start >= end) | ||||
| { | { | ||||
| data.exit(); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| else if (comparator.compareElements (elementToLookFor, data.elements [start]) == 0) | else if (comparator.compareElements (elementToLookFor, data.elements [start]) == 0) | ||||
| { | { | ||||
| data.exit(); | |||||
| return start; | return start; | ||||
| } | } | ||||
| else | else | ||||
| @@ -680,10 +619,7 @@ public: | |||||
| const int halfway = (start + end) >> 1; | const int halfway = (start + end) >> 1; | ||||
| if (halfway == start) | if (halfway == start) | ||||
| { | |||||
| data.exit(); | |||||
| return -1; | return -1; | ||||
| } | |||||
| else if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0) | else if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0) | ||||
| start = halfway; | start = halfway; | ||||
| else | else | ||||
| @@ -705,7 +641,7 @@ public: | |||||
| */ | */ | ||||
| ElementType remove (const int indexToRemove) | ElementType remove (const int indexToRemove) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) indexToRemove) < (unsigned int) numUsed) | if (((unsigned int) indexToRemove) < (unsigned int) numUsed) | ||||
| { | { | ||||
| @@ -722,12 +658,10 @@ public: | |||||
| if ((numUsed << 1) < data.numAllocated) | if ((numUsed << 1) < data.numAllocated) | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| data.exit(); | |||||
| return removed; | return removed; | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| data.exit(); | |||||
| return ElementType(); | return ElementType(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -742,7 +676,7 @@ public: | |||||
| */ | */ | ||||
| void removeValue (const ElementType& valueToRemove) | void removeValue (const ElementType& valueToRemove) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| ElementType* e = data.elements; | ElementType* e = data.elements; | ||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| @@ -755,8 +689,6 @@ public: | |||||
| ++e; | ++e; | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes a range of elements from the array. | /** Removes a range of elements from the array. | ||||
| @@ -773,7 +705,7 @@ public: | |||||
| */ | */ | ||||
| void removeRange (int startIndex, int numberToRemove) | void removeRange (int startIndex, int numberToRemove) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); | const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); | ||||
| startIndex = jlimit (0, numUsed, startIndex); | startIndex = jlimit (0, numUsed, startIndex); | ||||
| @@ -794,8 +726,6 @@ public: | |||||
| if ((numUsed << 1) < data.numAllocated) | if ((numUsed << 1) < data.numAllocated) | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes the last n elements from the array. | /** Removes the last n elements from the array. | ||||
| @@ -805,7 +735,7 @@ public: | |||||
| */ | */ | ||||
| void removeLast (int howManyToRemove = 1) | void removeLast (int howManyToRemove = 1) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (howManyToRemove > numUsed) | if (howManyToRemove > numUsed) | ||||
| howManyToRemove = numUsed; | howManyToRemove = numUsed; | ||||
| @@ -817,8 +747,6 @@ public: | |||||
| if ((numUsed << 1) < data.numAllocated) | if ((numUsed << 1) < data.numAllocated) | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes any elements which are also in another array. | /** Removes any elements which are also in another array. | ||||
| @@ -829,8 +757,8 @@ public: | |||||
| template <class OtherArrayType> | template <class OtherArrayType> | ||||
| void removeValuesIn (const OtherArrayType& otherArray) | void removeValuesIn (const OtherArrayType& otherArray) | ||||
| { | { | ||||
| otherArray.lockArray(); | |||||
| data.enter(); | |||||
| const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock()); | |||||
| const ScopedLockType lock2 (getLock()); | |||||
| if (this == &otherArray) | if (this == &otherArray) | ||||
| { | { | ||||
| @@ -845,9 +773,6 @@ public: | |||||
| remove (i); | remove (i); | ||||
| } | } | ||||
| } | } | ||||
| data.exit(); | |||||
| otherArray.unlockArray(); | |||||
| } | } | ||||
| /** Removes any elements which are not found in another array. | /** Removes any elements which are not found in another array. | ||||
| @@ -860,8 +785,8 @@ public: | |||||
| template <class OtherArrayType> | template <class OtherArrayType> | ||||
| void removeValuesNotIn (const OtherArrayType& otherArray) | void removeValuesNotIn (const OtherArrayType& otherArray) | ||||
| { | { | ||||
| otherArray.lockArray(); | |||||
| data.enter(); | |||||
| const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock()); | |||||
| const ScopedLockType lock2 (getLock()); | |||||
| if (this != &otherArray) | if (this != &otherArray) | ||||
| { | { | ||||
| @@ -876,9 +801,6 @@ public: | |||||
| remove (i); | remove (i); | ||||
| } | } | ||||
| } | } | ||||
| data.exit(); | |||||
| otherArray.unlockArray(); | |||||
| } | } | ||||
| /** Swaps over two elements in the array. | /** Swaps over two elements in the array. | ||||
| @@ -892,7 +814,7 @@ public: | |||||
| void swap (const int index1, | void swap (const int index1, | ||||
| const int index2) | const int index2) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) index1) < (unsigned int) numUsed | if (((unsigned int) index1) < (unsigned int) numUsed | ||||
| && ((unsigned int) index2) < (unsigned int) numUsed) | && ((unsigned int) index2) < (unsigned int) numUsed) | ||||
| @@ -900,8 +822,6 @@ public: | |||||
| swapVariables (data.elements [index1], | swapVariables (data.elements [index1], | ||||
| data.elements [index2]); | data.elements [index2]); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Moves one of the values to a different position. | /** Moves one of the values to a different position. | ||||
| @@ -922,7 +842,7 @@ public: | |||||
| { | { | ||||
| if (currentIndex != newIndex) | if (currentIndex != newIndex) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) currentIndex) < (unsigned int) numUsed) | if (((unsigned int) currentIndex) < (unsigned int) numUsed) | ||||
| { | { | ||||
| @@ -947,8 +867,6 @@ public: | |||||
| memcpy (data.elements + newIndex, tempCopy, sizeof (ElementType)); | memcpy (data.elements + newIndex, tempCopy, sizeof (ElementType)); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -961,9 +879,8 @@ public: | |||||
| */ | */ | ||||
| void minimiseStorageOverheads() | void minimiseStorageOverheads() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.shrinkToNoMoreThan (numUsed); | data.shrinkToNoMoreThan (numUsed); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Increases the array's internal storage to hold a minimum number of elements. | /** Increases the array's internal storage to hold a minimum number of elements. | ||||
| @@ -974,9 +891,8 @@ public: | |||||
| */ | */ | ||||
| void ensureStorageAllocated (const int minNumElements) | void ensureStorageAllocated (const int minNumElements) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (minNumElements); | data.ensureAllocatedSize (minNumElements); | ||||
| data.exit(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -1010,38 +926,21 @@ public: | |||||
| void sort (ElementComparator& comparator, | void sort (ElementComparator& comparator, | ||||
| const bool retainOrderOfEquivalentItems = false) const | const bool retainOrderOfEquivalentItems = false) const | ||||
| { | { | ||||
| const ScopedLockType lock (getLock()); | |||||
| (void) comparator; // if you pass in an object with a static compareElements() method, this | (void) comparator; // if you pass in an object with a static compareElements() method, this | ||||
| // avoids getting warning messages about the parameter being unused | // avoids getting warning messages about the parameter being unused | ||||
| data.enter(); | |||||
| sortArray (comparator, (ElementType*) data.elements, 0, size() - 1, retainOrderOfEquivalentItems); | 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 | juce_UseDebuggingNewOperator | ||||
| @@ -78,7 +78,7 @@ public: | |||||
| /** Clears the array, optionally deleting the objects inside it first. */ | /** Clears the array, optionally deleting the objects inside it first. */ | ||||
| void clear (const bool deleteObjects = true) | void clear (const bool deleteObjects = true) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (deleteObjects) | if (deleteObjects) | ||||
| { | { | ||||
| @@ -88,7 +88,6 @@ public: | |||||
| data.setAllocatedSize (0); | data.setAllocatedSize (0); | ||||
| numUsed = 0; | numUsed = 0; | ||||
| data.exit(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -110,13 +109,9 @@ public: | |||||
| */ | */ | ||||
| inline ObjectClass* operator[] (const int index) const throw() | 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. | /** 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() | inline ObjectClass* getUnchecked (const int index) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| jassert (((unsigned int) index) < (unsigned int) numUsed); | 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. | /** Returns a pointer to the first object in the array. | ||||
| @@ -141,11 +133,9 @@ public: | |||||
| */ | */ | ||||
| inline ObjectClass* getFirst() const throw() | 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. | /** Returns a pointer to the last object in the array. | ||||
| @@ -155,12 +145,9 @@ public: | |||||
| */ | */ | ||||
| inline ObjectClass* getLast() const throw() | 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 indexOf (const ObjectClass* const objectToLookFor) const throw() | ||||
| { | { | ||||
| int result = -1; | |||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| ObjectClass* const* e = data.elements; | ObjectClass* const* e = data.elements; | ||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| { | { | ||||
| if (objectToLookFor == *e) | if (objectToLookFor == *e) | ||||
| { | |||||
| result = (int) (e - data.elements); | |||||
| break; | |||||
| } | |||||
| return (int) (e - data.elements); | |||||
| ++e; | ++e; | ||||
| } | } | ||||
| data.exit(); | |||||
| return result; | |||||
| return -1; | |||||
| } | } | ||||
| /** Returns true if the array contains a specified object. | /** Returns true if the array contains a specified object. | ||||
| @@ -198,8 +179,7 @@ public: | |||||
| */ | */ | ||||
| bool contains (const ObjectClass* const objectToLookFor) const throw() | bool contains (const ObjectClass* const objectToLookFor) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| ObjectClass* const* e = data.elements; | ObjectClass* const* e = data.elements; | ||||
| int i = numUsed; | int i = numUsed; | ||||
| @@ -210,7 +190,6 @@ public: | |||||
| || objectToLookFor == *++e | || objectToLookFor == *++e | ||||
| || objectToLookFor == *++e) | || objectToLookFor == *++e) | ||||
| { | { | ||||
| data.exit(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -221,16 +200,12 @@ public: | |||||
| while (i > 0) | while (i > 0) | ||||
| { | { | ||||
| if (objectToLookFor == *e) | if (objectToLookFor == *e) | ||||
| { | |||||
| data.exit(); | |||||
| return true; | return true; | ||||
| } | |||||
| --i; | --i; | ||||
| ++e; | ++e; | ||||
| } | } | ||||
| data.exit(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -248,10 +223,9 @@ public: | |||||
| */ | */ | ||||
| void add (const ObjectClass* const newObject) throw() | void add (const ObjectClass* const newObject) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (numUsed + 1); | data.ensureAllocatedSize (numUsed + 1); | ||||
| data.elements [numUsed++] = const_cast <ObjectClass*> (newObject); | data.elements [numUsed++] = const_cast <ObjectClass*> (newObject); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Inserts a new object into the array at the given index. | /** Inserts a new object into the array at the given index. | ||||
| @@ -276,7 +250,7 @@ public: | |||||
| { | { | ||||
| if (indexToInsertAt >= 0) | if (indexToInsertAt >= 0) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (indexToInsertAt > numUsed) | if (indexToInsertAt > numUsed) | ||||
| indexToInsertAt = numUsed; | indexToInsertAt = numUsed; | ||||
| @@ -291,8 +265,6 @@ public: | |||||
| *e = const_cast <ObjectClass*> (newObject); | *e = const_cast <ObjectClass*> (newObject); | ||||
| ++numUsed; | ++numUsed; | ||||
| data.exit(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -309,12 +281,10 @@ public: | |||||
| */ | */ | ||||
| void addIfNotAlreadyThere (const ObjectClass* const newObject) throw() | void addIfNotAlreadyThere (const ObjectClass* const newObject) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (! contains (newObject)) | if (! contains (newObject)) | ||||
| add (newObject); | add (newObject); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Replaces an object in the array with a different one. | /** Replaces an object in the array with a different one. | ||||
| @@ -337,7 +307,7 @@ public: | |||||
| if (indexToChange >= 0) | if (indexToChange >= 0) | ||||
| { | { | ||||
| ScopedPointer <ObjectClass> toDelete; | ScopedPointer <ObjectClass> toDelete; | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (indexToChange < numUsed) | if (indexToChange < numUsed) | ||||
| { | { | ||||
| @@ -356,8 +326,6 @@ public: | |||||
| data.ensureAllocatedSize (numUsed + 1); | data.ensureAllocatedSize (numUsed + 1); | ||||
| data.elements [numUsed++] = const_cast <ObjectClass*> (newObject); | data.elements [numUsed++] = const_cast <ObjectClass*> (newObject); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -378,9 +346,8 @@ public: | |||||
| { | { | ||||
| (void) comparator; // if you pass in an object with a static compareElements() method, this | (void) comparator; // if you pass in an object with a static compareElements() method, this | ||||
| // avoids getting warning messages about the parameter being unused | // 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); | 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. | /** 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 | (void) comparator; // if you pass in an object with a static compareElements() method, this | ||||
| // avoids getting warning messages about the parameter being unused | // avoids getting warning messages about the parameter being unused | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| int start = 0; | int start = 0; | ||||
| int end = numUsed; | int end = numUsed; | ||||
| @@ -410,12 +377,10 @@ public: | |||||
| { | { | ||||
| if (start >= end) | if (start >= end) | ||||
| { | { | ||||
| data.exit(); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| else if (comparator.compareElements (objectToLookFor, data.elements [start]) == 0) | else if (comparator.compareElements (objectToLookFor, data.elements [start]) == 0) | ||||
| { | { | ||||
| data.exit(); | |||||
| return start; | return start; | ||||
| } | } | ||||
| else | else | ||||
| @@ -423,10 +388,7 @@ public: | |||||
| const int halfway = (start + end) >> 1; | const int halfway = (start + end) >> 1; | ||||
| if (halfway == start) | if (halfway == start) | ||||
| { | |||||
| data.exit(); | |||||
| return -1; | return -1; | ||||
| } | |||||
| else if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0) | else if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0) | ||||
| start = halfway; | start = halfway; | ||||
| else | else | ||||
| @@ -450,7 +412,7 @@ public: | |||||
| const bool deleteObject = true) | const bool deleteObject = true) | ||||
| { | { | ||||
| ScopedPointer <ObjectClass> toDelete; | ScopedPointer <ObjectClass> toDelete; | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) indexToRemove) < (unsigned int) numUsed) | if (((unsigned int) indexToRemove) < (unsigned int) numUsed) | ||||
| { | { | ||||
| @@ -468,8 +430,6 @@ public: | |||||
| if ((numUsed << 1) < data.numAllocated) | if ((numUsed << 1) < data.numAllocated) | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes a specified object from the array. | /** Removes a specified object from the array. | ||||
| @@ -483,7 +443,7 @@ public: | |||||
| void removeObject (const ObjectClass* const objectToRemove, | void removeObject (const ObjectClass* const objectToRemove, | ||||
| const bool deleteObject = true) | const bool deleteObject = true) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| ObjectClass** e = data.elements; | ObjectClass** e = data.elements; | ||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| @@ -496,8 +456,6 @@ public: | |||||
| ++e; | ++e; | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes a range of objects from the array. | /** Removes a range of objects from the array. | ||||
| @@ -517,7 +475,7 @@ public: | |||||
| const int numberToRemove, | const int numberToRemove, | ||||
| const bool deleteObjects = true) | const bool deleteObjects = true) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); | const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); | ||||
| startIndex = jlimit (0, numUsed, startIndex); | startIndex = jlimit (0, numUsed, startIndex); | ||||
| @@ -546,8 +504,6 @@ public: | |||||
| if ((numUsed << 1) < data.numAllocated) | if ((numUsed << 1) < data.numAllocated) | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes the last n objects from the array. | /** Removes the last n objects from the array. | ||||
| @@ -559,7 +515,7 @@ public: | |||||
| void removeLast (int howManyToRemove = 1, | void removeLast (int howManyToRemove = 1, | ||||
| const bool deleteObjects = true) | const bool deleteObjects = true) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (howManyToRemove >= numUsed) | if (howManyToRemove >= numUsed) | ||||
| { | { | ||||
| @@ -570,8 +526,6 @@ public: | |||||
| while (--howManyToRemove >= 0) | while (--howManyToRemove >= 0) | ||||
| remove (numUsed - 1, deleteObjects); | remove (numUsed - 1, deleteObjects); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Swaps a pair of objects in the array. | /** Swaps a pair of objects in the array. | ||||
| @@ -582,7 +536,7 @@ public: | |||||
| void swap (const int index1, | void swap (const int index1, | ||||
| const int index2) throw() | const int index2) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) index1) < (unsigned int) numUsed | if (((unsigned int) index1) < (unsigned int) numUsed | ||||
| && ((unsigned int) index2) < (unsigned int) numUsed) | && ((unsigned int) index2) < (unsigned int) numUsed) | ||||
| @@ -590,8 +544,6 @@ public: | |||||
| swapVariables (data.elements [index1], | swapVariables (data.elements [index1], | ||||
| data.elements [index2]); | data.elements [index2]); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Moves one of the objects to a different position. | /** Moves one of the objects to a different position. | ||||
| @@ -612,7 +564,7 @@ public: | |||||
| { | { | ||||
| if (currentIndex != newIndex) | if (currentIndex != newIndex) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) currentIndex) < (unsigned int) numUsed) | if (((unsigned int) currentIndex) < (unsigned int) numUsed) | ||||
| { | { | ||||
| @@ -636,8 +588,6 @@ public: | |||||
| data.elements [newIndex] = value; | 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 | If you need to exchange two arrays, this is vastly quicker than using copy-by-value | ||||
| because it just swaps their internal pointers. | because it just swaps their internal pointers. | ||||
| */ | */ | ||||
| void swapWithArray (OwnedArray <ObjectClass>& otherArray) throw() | |||||
| void swapWithArray (OwnedArray& otherArray) throw() | |||||
| { | { | ||||
| data.enter(); | |||||
| otherArray.data.enter(); | |||||
| const ScopedLockType lock1 (getLock()); | |||||
| const ScopedLockType lock2 (otherArray.getLock()); | |||||
| data.swapWith (otherArray.data); | data.swapWith (otherArray.data); | ||||
| swapVariables (numUsed, otherArray.numUsed); | swapVariables (numUsed, otherArray.numUsed); | ||||
| otherArray.data.exit(); | |||||
| data.exit(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -665,9 +614,8 @@ public: | |||||
| */ | */ | ||||
| void minimiseStorageOverheads() throw() | void minimiseStorageOverheads() throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.shrinkToNoMoreThan (numUsed); | data.shrinkToNoMoreThan (numUsed); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Increases the array's internal storage to hold a minimum number of elements. | /** Increases the array's internal storage to hold a minimum number of elements. | ||||
| @@ -678,9 +626,8 @@ public: | |||||
| */ | */ | ||||
| void ensureStorageAllocated (const int minNumElements) throw() | void ensureStorageAllocated (const int minNumElements) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (minNumElements); | data.ensureAllocatedSize (minNumElements); | ||||
| data.exit(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -716,35 +663,19 @@ public: | |||||
| (void) comparator; // if you pass in an object with a static compareElements() method, this | (void) comparator; // if you pass in an object with a static compareElements() method, this | ||||
| // avoids getting warning messages about the parameter being unused | // avoids getting warning messages about the parameter being unused | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| sortArray (comparator, (ObjectClass**) data.elements, 0, size() - 1, retainOrderOfEquivalentItems); | 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; | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -61,7 +61,7 @@ public: | |||||
| /** Creates a copy of another array */ | /** Creates a copy of another array */ | ||||
| ReferenceCountedArray (const ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& other) throw() | ReferenceCountedArray (const ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& other) throw() | ||||
| { | { | ||||
| other.lockArray(); | |||||
| const ScopedLockType lock (other.getLock()); | |||||
| numUsed = other.numUsed; | numUsed = other.numUsed; | ||||
| data.setAllocatedSize (numUsed); | data.setAllocatedSize (numUsed); | ||||
| memcpy (data.elements, other.data.elements, numUsed * sizeof (ObjectClass*)); | memcpy (data.elements, other.data.elements, numUsed * sizeof (ObjectClass*)); | ||||
| @@ -69,8 +69,6 @@ public: | |||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| if (data.elements[i] != 0) | if (data.elements[i] != 0) | ||||
| data.elements[i]->incReferenceCount(); | data.elements[i]->incReferenceCount(); | ||||
| other.unlockArray(); | |||||
| } | } | ||||
| /** Copies another array into this one. | /** Copies another array into this one. | ||||
| @@ -104,7 +102,7 @@ public: | |||||
| */ | */ | ||||
| void clear() | void clear() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| while (numUsed > 0) | while (numUsed > 0) | ||||
| if (data.elements [--numUsed] != 0) | if (data.elements [--numUsed] != 0) | ||||
| @@ -112,8 +110,6 @@ public: | |||||
| jassert (numUsed == 0); | jassert (numUsed == 0); | ||||
| data.setAllocatedSize (0); | data.setAllocatedSize (0); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Returns the current number of objects in the array. */ | /** Returns the current number of objects in the array. */ | ||||
| @@ -132,12 +128,9 @@ public: | |||||
| */ | */ | ||||
| inline const ReferenceCountedObjectPtr<ObjectClass> operator[] (const int index) const throw() | inline const ReferenceCountedObjectPtr<ObjectClass> operator[] (const int index) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((((unsigned int) index) < (unsigned int) numUsed) | |||||
| ? data.elements [index] | |||||
| : (ObjectClass*) 0); | |||||
| data.exit(); | |||||
| return result; | |||||
| const ScopedLockType lock (getLock()); | |||||
| return (((unsigned int) index) < (unsigned int) numUsed) ? data.elements [index] | |||||
| : (ObjectClass*) 0; | |||||
| } | } | ||||
| /** Returns a pointer to the object at this index in the array, without checking whether the index is in-range. | /** Returns a pointer to the object at this index in the array, without checking whether the index is in-range. | ||||
| @@ -147,11 +140,9 @@ public: | |||||
| */ | */ | ||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getUnchecked (const int index) const throw() | inline const ReferenceCountedObjectPtr<ObjectClass> getUnchecked (const int index) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| jassert (((unsigned int) index) < (unsigned int) numUsed); | jassert (((unsigned int) index) < (unsigned int) numUsed); | ||||
| const ReferenceCountedObjectPtr<ObjectClass> result (data.elements [index]); | |||||
| data.exit(); | |||||
| return result; | |||||
| return data.elements [index]; | |||||
| } | } | ||||
| /** Returns a pointer to the first object in the array. | /** Returns a pointer to the first object in the array. | ||||
| @@ -161,12 +152,9 @@ public: | |||||
| */ | */ | ||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getFirst() const throw() | inline const ReferenceCountedObjectPtr<ObjectClass> getFirst() const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((numUsed > 0) ? data.elements [0] | |||||
| : (ObjectClass*) 0); | |||||
| data.exit(); | |||||
| return result; | |||||
| const ScopedLockType lock (getLock()); | |||||
| return numUsed > 0 ? data.elements [0] | |||||
| : (ObjectClass*) 0; | |||||
| } | } | ||||
| /** Returns a pointer to the last object in the array. | /** Returns a pointer to the last object in the array. | ||||
| @@ -176,12 +164,9 @@ public: | |||||
| */ | */ | ||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getLast() const throw() | inline const ReferenceCountedObjectPtr<ObjectClass> getLast() const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((numUsed > 0) ? data.elements [numUsed - 1] | |||||
| : (ObjectClass*) 0); | |||||
| data.exit(); | |||||
| return result; | |||||
| const ScopedLockType lock (getLock()); | |||||
| return numUsed > 0 ? data.elements [numUsed - 1] | |||||
| : (ObjectClass*) 0; | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -192,24 +177,18 @@ public: | |||||
| */ | */ | ||||
| int indexOf (const ObjectClass* const objectToLookFor) const throw() | int indexOf (const ObjectClass* const objectToLookFor) const throw() | ||||
| { | { | ||||
| int result = -1; | |||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| ObjectClass** e = data.elements; | ObjectClass** e = data.elements; | ||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| { | { | ||||
| if (objectToLookFor == *e) | if (objectToLookFor == *e) | ||||
| { | |||||
| result = (int) (e - data.elements); | |||||
| break; | |||||
| } | |||||
| return (int) (e - data.elements); | |||||
| ++e; | ++e; | ||||
| } | } | ||||
| data.exit(); | |||||
| return result; | |||||
| return -1; | |||||
| } | } | ||||
| /** Returns true if the array contains a specified object. | /** Returns true if the array contains a specified object. | ||||
| @@ -219,21 +198,17 @@ public: | |||||
| */ | */ | ||||
| bool contains (const ObjectClass* const objectToLookFor) const throw() | bool contains (const ObjectClass* const objectToLookFor) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| ObjectClass** e = data.elements; | ObjectClass** e = data.elements; | ||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| { | { | ||||
| if (objectToLookFor == *e) | if (objectToLookFor == *e) | ||||
| { | |||||
| data.exit(); | |||||
| return true; | return true; | ||||
| } | |||||
| ++e; | ++e; | ||||
| } | } | ||||
| data.exit(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -246,14 +221,12 @@ public: | |||||
| */ | */ | ||||
| void add (ObjectClass* const newObject) throw() | void add (ObjectClass* const newObject) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.ensureAllocatedSize (numUsed + 1); | data.ensureAllocatedSize (numUsed + 1); | ||||
| data.elements [numUsed++] = newObject; | data.elements [numUsed++] = newObject; | ||||
| if (newObject != 0) | if (newObject != 0) | ||||
| newObject->incReferenceCount(); | newObject->incReferenceCount(); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Inserts a new object into the array at the given index. | /** Inserts a new object into the array at the given index. | ||||
| @@ -274,7 +247,7 @@ public: | |||||
| { | { | ||||
| if (indexToInsertAt >= 0) | if (indexToInsertAt >= 0) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (indexToInsertAt > numUsed) | if (indexToInsertAt > numUsed) | ||||
| indexToInsertAt = numUsed; | indexToInsertAt = numUsed; | ||||
| @@ -293,7 +266,6 @@ public: | |||||
| newObject->incReferenceCount(); | newObject->incReferenceCount(); | ||||
| ++numUsed; | ++numUsed; | ||||
| data.exit(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -310,12 +282,9 @@ public: | |||||
| */ | */ | ||||
| void addIfNotAlreadyThere (ObjectClass* const newObject) throw() | void addIfNotAlreadyThere (ObjectClass* const newObject) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (! contains (newObject)) | if (! contains (newObject)) | ||||
| add (newObject); | add (newObject); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Replaces an object in the array with a different one. | /** Replaces an object in the array with a different one. | ||||
| @@ -335,7 +304,7 @@ public: | |||||
| { | { | ||||
| if (indexToChange >= 0) | if (indexToChange >= 0) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (newObject != 0) | if (newObject != 0) | ||||
| newObject->incReferenceCount(); | newObject->incReferenceCount(); | ||||
| @@ -352,8 +321,6 @@ public: | |||||
| data.ensureAllocatedSize (numUsed + 1); | data.ensureAllocatedSize (numUsed + 1); | ||||
| data.elements [numUsed++] = newObject; | data.elements [numUsed++] = newObject; | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -371,7 +338,7 @@ public: | |||||
| int numElementsToAdd = -1) throw() | int numElementsToAdd = -1) throw() | ||||
| { | { | ||||
| arrayToAddFrom.lockArray(); | arrayToAddFrom.lockArray(); | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (startIndex < 0) | if (startIndex < 0) | ||||
| { | { | ||||
| @@ -390,7 +357,6 @@ public: | |||||
| add (arrayToAddFrom.getUnchecked (startIndex++)); | add (arrayToAddFrom.getUnchecked (startIndex++)); | ||||
| } | } | ||||
| data.exit(); | |||||
| arrayToAddFrom.unlockArray(); | arrayToAddFrom.unlockArray(); | ||||
| } | } | ||||
| @@ -409,9 +375,8 @@ public: | |||||
| void addSorted (ElementComparator& comparator, | void addSorted (ElementComparator& comparator, | ||||
| ObjectClass* newObject) throw() | ObjectClass* newObject) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| insert (findInsertIndexInSortedArray (comparator, (ObjectClass**) data.elements, newObject, 0, numUsed), newObject); | insert (findInsertIndexInSortedArray (comparator, (ObjectClass**) data.elements, newObject, 0, numUsed), newObject); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Inserts or replaces an object in the array, assuming it is sorted. | /** Inserts or replaces an object in the array, assuming it is sorted. | ||||
| @@ -423,15 +388,13 @@ public: | |||||
| void addOrReplaceSorted (ElementComparator& comparator, | void addOrReplaceSorted (ElementComparator& comparator, | ||||
| ObjectClass* newObject) throw() | ObjectClass* newObject) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| const int index = findInsertIndexInSortedArray (comparator, (ObjectClass**) data.elements, newObject, 0, numUsed); | const int index = findInsertIndexInSortedArray (comparator, (ObjectClass**) data.elements, newObject, 0, numUsed); | ||||
| if (index > 0 && comparator.compareElements (newObject, data.elements [index - 1]) == 0) | if (index > 0 && comparator.compareElements (newObject, data.elements [index - 1]) == 0) | ||||
| set (index - 1, newObject); // replace an existing object that matches | set (index - 1, newObject); // replace an existing object that matches | ||||
| else | else | ||||
| insert (index, newObject); // no match, so insert the new one | insert (index, newObject); // no match, so insert the new one | ||||
| data.exit(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -450,7 +413,7 @@ public: | |||||
| */ | */ | ||||
| void remove (const int indexToRemove) | void remove (const int indexToRemove) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) indexToRemove) < (unsigned int) numUsed) | if (((unsigned int) indexToRemove) < (unsigned int) numUsed) | ||||
| { | { | ||||
| @@ -468,8 +431,6 @@ public: | |||||
| if ((numUsed << 1) < data.numAllocated) | if ((numUsed << 1) < data.numAllocated) | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes the first occurrence of a specified object from the array. | /** Removes the first occurrence of a specified object from the array. | ||||
| @@ -482,9 +443,8 @@ public: | |||||
| */ | */ | ||||
| void removeObject (ObjectClass* const objectToRemove) | void removeObject (ObjectClass* const objectToRemove) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| remove (indexOf (objectToRemove)); | remove (indexOf (objectToRemove)); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes a range of objects from the array. | /** Removes a range of objects from the array. | ||||
| @@ -505,7 +465,7 @@ public: | |||||
| void removeRange (const int startIndex, | void removeRange (const int startIndex, | ||||
| const int numberToRemove) | const int numberToRemove) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| const int start = jlimit (0, numUsed, startIndex); | const int start = jlimit (0, numUsed, startIndex); | ||||
| const int end = jlimit (0, numUsed, startIndex + numberToRemove); | const int end = jlimit (0, numUsed, startIndex + numberToRemove); | ||||
| @@ -536,8 +496,6 @@ public: | |||||
| if ((numUsed << 1) < data.numAllocated) | if ((numUsed << 1) < data.numAllocated) | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes the last n objects from the array. | /** Removes the last n objects from the array. | ||||
| @@ -550,15 +508,13 @@ public: | |||||
| */ | */ | ||||
| void removeLast (int howManyToRemove = 1) | void removeLast (int howManyToRemove = 1) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (howManyToRemove > numUsed) | if (howManyToRemove > numUsed) | ||||
| howManyToRemove = numUsed; | howManyToRemove = numUsed; | ||||
| while (--howManyToRemove >= 0) | while (--howManyToRemove >= 0) | ||||
| remove (numUsed - 1); | remove (numUsed - 1); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Swaps a pair of objects in the array. | /** Swaps a pair of objects in the array. | ||||
| @@ -569,7 +525,7 @@ public: | |||||
| void swap (const int index1, | void swap (const int index1, | ||||
| const int index2) throw() | const int index2) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) index1) < (unsigned int) numUsed | if (((unsigned int) index1) < (unsigned int) numUsed | ||||
| && ((unsigned int) index2) < (unsigned int) numUsed) | && ((unsigned int) index2) < (unsigned int) numUsed) | ||||
| @@ -577,8 +533,6 @@ public: | |||||
| swapVariables (data.elements [index1], | swapVariables (data.elements [index1], | ||||
| data.elements [index2]); | data.elements [index2]); | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Moves one of the objects to a different position. | /** Moves one of the objects to a different position. | ||||
| @@ -599,7 +553,7 @@ public: | |||||
| { | { | ||||
| if (currentIndex != newIndex) | if (currentIndex != newIndex) | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) currentIndex) < (unsigned int) numUsed) | if (((unsigned int) currentIndex) < (unsigned int) numUsed) | ||||
| { | { | ||||
| @@ -623,8 +577,6 @@ public: | |||||
| data.elements [newIndex] = value; | 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 | If you need to exchange two arrays, this is vastly quicker than using copy-by-value | ||||
| because it just swaps their internal pointers. | because it just swaps their internal pointers. | ||||
| */ | */ | ||||
| void swapWithArray (ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& otherArray) throw() | |||||
| void swapWithArray (ReferenceCountedArray& otherArray) throw() | |||||
| { | { | ||||
| data.enter(); | |||||
| otherArray.data.enter(); | |||||
| const ScopedLockType lock1 (getLock()); | |||||
| const ScopedLockType lock2 (otherArray.getLock()); | |||||
| data.swapWith (otherArray.data); | data.swapWith (otherArray.data); | ||||
| swapVariables (numUsed, otherArray.numUsed); | 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 | @returns true only if the other array contains the same objects in the same order | ||||
| */ | */ | ||||
| bool operator== (const ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>& other) const throw() | |||||
| bool operator== (const ReferenceCountedArray& other) const throw() | |||||
| { | { | ||||
| other.lockArray(); | |||||
| data.enter(); | |||||
| const ScopedLockType lock2 (other.getLock()); | |||||
| const ScopedLockType lock1 (getLock()); | |||||
| bool result = numUsed == other.numUsed; | |||||
| if (numUsed != other.numUsed) | |||||
| return false; | |||||
| if (result) | |||||
| { | |||||
| for (int i = numUsed; --i >= 0;) | |||||
| { | |||||
| if (data.elements [i] != other.data.elements [i]) | |||||
| { | |||||
| result = false; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| data.exit(); | |||||
| other.unlockArray(); | |||||
| for (int i = numUsed; --i >= 0;) | |||||
| if (data.elements [i] != other.data.elements [i]) | |||||
| return false; | |||||
| return result; | |||||
| return true; | |||||
| } | } | ||||
| /** Compares this array to another one. | /** 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 | (void) comparator; // if you pass in an object with a static compareElements() method, this | ||||
| // avoids getting warning messages about the parameter being unused | // avoids getting warning messages about the parameter being unused | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| sortArray (comparator, (ObjectClass**) data.elements, 0, size() - 1, retainOrderOfEquivalentItems); | sortArray (comparator, (ObjectClass**) data.elements, 0, size() - 1, retainOrderOfEquivalentItems); | ||||
| data.exit(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -731,35 +671,19 @@ public: | |||||
| */ | */ | ||||
| void minimiseStorageOverheads() throw() | void minimiseStorageOverheads() throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.shrinkToNoMoreThan (numUsed); | 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; | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -71,13 +71,12 @@ public: | |||||
| /** Creates a copy of another set. | /** Creates a copy of another set. | ||||
| @param other the set to copy | @param other the set to copy | ||||
| */ | */ | ||||
| SortedSet (const SortedSet<ElementType, TypeOfCriticalSectionToUse>& other) throw() | |||||
| SortedSet (const SortedSet& other) throw() | |||||
| { | { | ||||
| other.lockSet(); | |||||
| const ScopedLockType lock (other.getLock()); | |||||
| numUsed = other.numUsed; | numUsed = other.numUsed; | ||||
| data.setAllocatedSize (other.numUsed); | data.setAllocatedSize (other.numUsed); | ||||
| memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); | memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); | ||||
| other.unlockSet(); | |||||
| } | } | ||||
| /** Destructor. */ | /** Destructor. */ | ||||
| @@ -88,20 +87,17 @@ public: | |||||
| /** Copies another set over this one. | /** Copies another set over this one. | ||||
| @param other the set to copy | @param other the set to copy | ||||
| */ | */ | ||||
| SortedSet <ElementType, TypeOfCriticalSectionToUse>& operator= (const SortedSet <ElementType, TypeOfCriticalSectionToUse>& other) throw() | |||||
| SortedSet& operator= (const SortedSet& other) throw() | |||||
| { | { | ||||
| if (this != &other) | if (this != &other) | ||||
| { | { | ||||
| other.lockSet(); | |||||
| data.enter(); | |||||
| const ScopedLockType lock1 (other.getLock()); | |||||
| const ScopedLockType lock2 (getLock()); | |||||
| data.ensureAllocatedSize (other.size()); | data.ensureAllocatedSize (other.size()); | ||||
| numUsed = other.numUsed; | numUsed = other.numUsed; | ||||
| memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); | memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| data.exit(); | |||||
| other.unlockSet(); | |||||
| } | } | ||||
| return *this; | return *this; | ||||
| @@ -117,24 +113,15 @@ public: | |||||
| */ | */ | ||||
| bool operator== (const SortedSet<ElementType>& other) const throw() | bool operator== (const SortedSet<ElementType>& other) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (numUsed != other.numUsed) | if (numUsed != other.numUsed) | ||||
| { | |||||
| data.exit(); | |||||
| return false; | return false; | ||||
| } | |||||
| for (int i = numUsed; --i >= 0;) | 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; | return false; | ||||
| } | |||||
| } | |||||
| data.exit(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -161,10 +148,9 @@ public: | |||||
| */ | */ | ||||
| void clear() throw() | void clear() throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.setAllocatedSize (0); | data.setAllocatedSize (0); | ||||
| numUsed = 0; | numUsed = 0; | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes all elements from the set without freeing the array's allocated storage. | /** Removes all elements from the set without freeing the array's allocated storage. | ||||
| @@ -173,9 +159,8 @@ public: | |||||
| */ | */ | ||||
| void clearQuick() throw() | void clearQuick() throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| numUsed = 0; | numUsed = 0; | ||||
| data.exit(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -199,13 +184,9 @@ public: | |||||
| */ | */ | ||||
| inline ElementType operator[] (const int index) const throw() | 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. | /** 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() | inline ElementType getUnchecked (const int index) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| jassert (((unsigned int) index) < (unsigned int) numUsed); | 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. | /** Returns the first element in the set, or 0 if the set is empty. | ||||
| @@ -232,12 +210,8 @@ public: | |||||
| */ | */ | ||||
| inline ElementType getFirst() const throw() | 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. | /** Returns the last element in the set, or 0 if the set is empty. | ||||
| @@ -246,12 +220,8 @@ public: | |||||
| */ | */ | ||||
| inline ElementType getLast() const throw() | 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() | int indexOf (const ElementType elementToLookFor) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| int start = 0; | int start = 0; | ||||
| int end = numUsed; | int end = numUsed; | ||||
| @@ -274,12 +244,10 @@ public: | |||||
| { | { | ||||
| if (start >= end) | if (start >= end) | ||||
| { | { | ||||
| data.exit(); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| else if (elementToLookFor == data.elements [start]) | else if (elementToLookFor == data.elements [start]) | ||||
| { | { | ||||
| data.exit(); | |||||
| return start; | return start; | ||||
| } | } | ||||
| else | else | ||||
| @@ -287,10 +255,7 @@ public: | |||||
| const int halfway = (start + end) >> 1; | const int halfway = (start + end) >> 1; | ||||
| if (halfway == start) | if (halfway == start) | ||||
| { | |||||
| data.exit(); | |||||
| return -1; | return -1; | ||||
| } | |||||
| else if (elementToLookFor >= data.elements [halfway]) | else if (elementToLookFor >= data.elements [halfway]) | ||||
| start = halfway; | start = halfway; | ||||
| else | else | ||||
| @@ -306,7 +271,7 @@ public: | |||||
| */ | */ | ||||
| bool contains (const ElementType elementToLookFor) const throw() | bool contains (const ElementType elementToLookFor) const throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| int start = 0; | int start = 0; | ||||
| int end = numUsed; | int end = numUsed; | ||||
| @@ -315,12 +280,10 @@ public: | |||||
| { | { | ||||
| if (start >= end) | if (start >= end) | ||||
| { | { | ||||
| data.exit(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| else if (elementToLookFor == data.elements [start]) | else if (elementToLookFor == data.elements [start]) | ||||
| { | { | ||||
| data.exit(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| else | else | ||||
| @@ -328,10 +291,7 @@ public: | |||||
| const int halfway = (start + end) >> 1; | const int halfway = (start + end) >> 1; | ||||
| if (halfway == start) | if (halfway == start) | ||||
| { | |||||
| data.exit(); | |||||
| return false; | return false; | ||||
| } | |||||
| else if (elementToLookFor >= data.elements [halfway]) | else if (elementToLookFor >= data.elements [halfway]) | ||||
| start = halfway; | start = halfway; | ||||
| else | else | ||||
| @@ -348,7 +308,7 @@ public: | |||||
| */ | */ | ||||
| void add (const ElementType newElement) throw() | void add (const ElementType newElement) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| int start = 0; | int start = 0; | ||||
| int end = numUsed; | int end = numUsed; | ||||
| @@ -384,8 +344,6 @@ public: | |||||
| end = halfway; | end = halfway; | ||||
| } | } | ||||
| } | } | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Adds elements from an array to this set. | /** Adds elements from an array to this set. | ||||
| @@ -397,12 +355,10 @@ public: | |||||
| void addArray (const ElementType* elementsToAdd, | void addArray (const ElementType* elementsToAdd, | ||||
| int numElementsToAdd) throw() | int numElementsToAdd) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| while (--numElementsToAdd >= 0) | while (--numElementsToAdd >= 0) | ||||
| add (*elementsToAdd++); | add (*elementsToAdd++); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Adds elements from another set to this one. | /** Adds elements from another set to this one. | ||||
| @@ -419,8 +375,8 @@ public: | |||||
| int startIndex = 0, | int startIndex = 0, | ||||
| int numElementsToAdd = -1) throw() | int numElementsToAdd = -1) throw() | ||||
| { | { | ||||
| setToAddFrom.lockSet(); | |||||
| data.enter(); | |||||
| const typename OtherSetType::ScopedLockType lock1 (setToAddFrom.getLock()); | |||||
| const ScopedLockType lock2 (getLock()); | |||||
| jassert (this != &setToAddFrom); | jassert (this != &setToAddFrom); | ||||
| if (this != &setToAddFrom) | if (this != &setToAddFrom) | ||||
| @@ -436,9 +392,6 @@ public: | |||||
| addArray (setToAddFrom.elements + startIndex, numElementsToAdd); | addArray (setToAddFrom.elements + startIndex, numElementsToAdd); | ||||
| } | } | ||||
| data.exit(); | |||||
| setToAddFrom.unlockSet(); | |||||
| } | } | ||||
| @@ -454,7 +407,7 @@ public: | |||||
| */ | */ | ||||
| ElementType remove (const int indexToRemove) throw() | ElementType remove (const int indexToRemove) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| if (((unsigned int) indexToRemove) < (unsigned int) numUsed) | if (((unsigned int) indexToRemove) < (unsigned int) numUsed) | ||||
| { | { | ||||
| @@ -470,14 +423,10 @@ public: | |||||
| if ((numUsed << 1) < data.numAllocated) | if ((numUsed << 1) < data.numAllocated) | ||||
| minimiseStorageOverheads(); | minimiseStorageOverheads(); | ||||
| data.exit(); | |||||
| return removed; | return removed; | ||||
| } | } | ||||
| else | |||||
| { | |||||
| data.exit(); | |||||
| return 0; | |||||
| } | |||||
| return 0; | |||||
| } | } | ||||
| /** Removes an item from the set. | /** Removes an item from the set. | ||||
| @@ -489,9 +438,8 @@ public: | |||||
| */ | */ | ||||
| void removeValue (const ElementType valueToRemove) throw() | void removeValue (const ElementType valueToRemove) throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| remove (indexOf (valueToRemove)); | remove (indexOf (valueToRemove)); | ||||
| data.exit(); | |||||
| } | } | ||||
| /** Removes any elements which are also in another set. | /** Removes any elements which are also in another set. | ||||
| @@ -502,8 +450,8 @@ public: | |||||
| template <class OtherSetType> | template <class OtherSetType> | ||||
| void removeValuesIn (const OtherSetType& otherSet) throw() | void removeValuesIn (const OtherSetType& otherSet) throw() | ||||
| { | { | ||||
| otherSet.lockSet(); | |||||
| data.enter(); | |||||
| const typename OtherSetType::ScopedLockType lock1 (otherSet.getLock()); | |||||
| const ScopedLockType lock2 (getLock()); | |||||
| if (this == &otherSet) | if (this == &otherSet) | ||||
| { | { | ||||
| @@ -518,9 +466,6 @@ public: | |||||
| remove (i); | remove (i); | ||||
| } | } | ||||
| } | } | ||||
| data.exit(); | |||||
| otherSet.unlockSet(); | |||||
| } | } | ||||
| /** Removes any elements which are not found in another set. | /** Removes any elements which are not found in another set. | ||||
| @@ -533,8 +478,8 @@ public: | |||||
| template <class OtherSetType> | template <class OtherSetType> | ||||
| void removeValuesNotIn (const OtherSetType& otherSet) throw() | void removeValuesNotIn (const OtherSetType& otherSet) throw() | ||||
| { | { | ||||
| otherSet.lockSet(); | |||||
| data.enter(); | |||||
| const typename OtherSetType::ScopedLockType lock1 (otherSet.getLock()); | |||||
| const ScopedLockType lock2 (getLock()); | |||||
| if (this != &otherSet) | if (this != &otherSet) | ||||
| { | { | ||||
| @@ -549,9 +494,6 @@ public: | |||||
| remove (i); | remove (i); | ||||
| } | } | ||||
| } | } | ||||
| data.exit(); | |||||
| otherSet.lockSet(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -563,35 +505,19 @@ public: | |||||
| */ | */ | ||||
| void minimiseStorageOverheads() throw() | void minimiseStorageOverheads() throw() | ||||
| { | { | ||||
| data.enter(); | |||||
| const ScopedLockType lock (getLock()); | |||||
| data.shrinkToNoMoreThan (numUsed); | 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; | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -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 | accessed from another thread inside a MM lock, you're screwed. (this is exactly what happens | ||||
| in Cocoa). | in Cocoa). | ||||
| */ | */ | ||||
| class SharedLockingEvents : public ReferenceCountedObject | |||||
| class MessageManagerLock::SharedEvents : public ReferenceCountedObject | |||||
| { | { | ||||
| public: | 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, | 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. */ | this shared data must be kept in a separate, ref-counted container. */ | ||||
| WaitableEvent lockedEvent, releaseEvent; | WaitableEvent lockedEvent, releaseEvent; | ||||
| private: | |||||
| SharedEvents (const SharedEvents&); | |||||
| SharedEvents& operator= (const SharedEvents&); | |||||
| }; | }; | ||||
| class MMLockMessage : public CallbackMessage | |||||
| class MessageManagerLock::BlockingMessage : public CallbackMessage | |||||
| { | { | ||||
| public: | public: | ||||
| MMLockMessage (SharedLockingEvents* const events_) throw() | |||||
| : events (events_) | |||||
| {} | |||||
| ~MMLockMessage() throw() {} | |||||
| ReferenceCountedObjectPtr <SharedLockingEvents> events; | |||||
| BlockingMessage (MessageManagerLock::SharedEvents* const events_) : events (events_) {} | |||||
| ~BlockingMessage() throw() {} | |||||
| void messageCallback() | void messageCallback() | ||||
| { | { | ||||
| @@ -260,21 +259,24 @@ public: | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| MMLockMessage (const MMLockMessage&); | |||||
| const MMLockMessage& operator= (const MMLockMessage&); | |||||
| private: | |||||
| ReferenceCountedObjectPtr <MessageManagerLock::SharedEvents> events; | |||||
| BlockingMessage (const BlockingMessage&); | |||||
| BlockingMessage& operator= (const BlockingMessage&); | |||||
| }; | }; | ||||
| //============================================================================== | //============================================================================== | ||||
| MessageManagerLock::MessageManagerLock (Thread* const threadToCheck) throw() | MessageManagerLock::MessageManagerLock (Thread* const threadToCheck) throw() | ||||
| : locked (false), | |||||
| needsUnlocking (false) | |||||
| : sharedEvents (0), | |||||
| locked (false) | |||||
| { | { | ||||
| init (threadToCheck, 0); | init (threadToCheck, 0); | ||||
| } | } | ||||
| MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw() | MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw() | ||||
| : locked (false), | |||||
| needsUnlocking (false) | |||||
| : sharedEvents (0), | |||||
| locked (false) | |||||
| { | { | ||||
| init (0, jobToCheckForExitSignal); | 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()) | if ((threadToCheck != 0 && threadToCheck->threadShouldExit()) | ||||
| || (job != 0 && job->shouldExit())) | || (job != 0 && job->shouldExit())) | ||||
| { | { | ||||
| events->releaseEvent.signal(); | |||||
| events->decReferenceCount(); | |||||
| sharedEvents->releaseEvent.signal(); | |||||
| sharedEvents->decReferenceCount(); | |||||
| sharedEvents = 0; | |||||
| MessageManager::instance->lockingLock.exit(); | MessageManager::instance->lockingLock.exit(); | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -327,22 +329,24 @@ void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const | |||||
| MessageManager::instance->threadWithLock = Thread::getCurrentThreadId(); | MessageManager::instance->threadWithLock = Thread::getCurrentThreadId(); | ||||
| locked = true; | locked = true; | ||||
| needsUnlocking = true; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| MessageManagerLock::~MessageManagerLock() throw() | 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(); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -305,13 +305,15 @@ public: | |||||
| private: | private: | ||||
| bool locked, needsUnlocking; | |||||
| void* sharedEvents; | |||||
| class SharedEvents; | |||||
| class BlockingMessage; | |||||
| SharedEvents* sharedEvents; | |||||
| bool locked; | |||||
| void init (Thread* const thread, ThreadPoolJob* const job) throw(); | void init (Thread* const thread, ThreadPoolJob* const job) throw(); | ||||
| MessageManagerLock (const MessageManagerLock&); | MessageManagerLock (const MessageManagerLock&); | ||||
| const MessageManagerLock& operator= (const MessageManagerLock&); | |||||
| MessageManagerLock& operator= (const MessageManagerLock&); | |||||
| }; | }; | ||||
| @@ -79,11 +79,15 @@ public: | |||||
| const int elapsed = now - lastTime; | const int elapsed = now - lastTime; | ||||
| lastTime = now; | 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) | if (timeUntilFirstTimer <= 0) | ||||
| { | { | ||||
| @@ -1168,16 +1168,19 @@ void TreeViewItem::addSubItem (TreeViewItem* const newItem, const int insertPosi | |||||
| void TreeViewItem::removeSubItem (const int index, const bool deleteItem) | void TreeViewItem::removeSubItem (const int index, const bool deleteItem) | ||||
| { | { | ||||
| if (ownerView != 0) | 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); | subItems.remove (index, deleteItem); | ||||
| treeHasChanged(); | |||||
| } | } | ||||
| if (ownerView != 0) | |||||
| ownerView->nodeAlterationLock.exit(); | |||||
| } | } | ||||
| bool TreeViewItem::isOpen() const throw() | bool TreeViewItem::isOpen() const throw() | ||||
| @@ -29,7 +29,7 @@ BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_OutputStream.h" | #include "juce_OutputStream.h" | ||||
| #include "../../threads/juce_CriticalSection.h" | |||||
| #include "../../threads/juce_ScopedLock.h" | |||||
| #include "../../containers/juce_VoidArray.h" | #include "../../containers/juce_VoidArray.h" | ||||
| @@ -54,18 +54,16 @@ void juce_CheckForDanglingStreams() | |||||
| OutputStream::OutputStream() throw() | OutputStream::OutputStream() throw() | ||||
| { | { | ||||
| #if JUCE_DEBUG | #if JUCE_DEBUG | ||||
| activeStreamLock.enter(); | |||||
| const ScopedLock sl (activeStreamLock); | |||||
| activeStreams.add (this); | activeStreams.add (this); | ||||
| activeStreamLock.exit(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| OutputStream::~OutputStream() | OutputStream::~OutputStream() | ||||
| { | { | ||||
| #if JUCE_DEBUG | #if JUCE_DEBUG | ||||
| activeStreamLock.enter(); | |||||
| const ScopedLock sl (activeStreamLock); | |||||
| activeStreams.removeValue (this); | activeStreams.removeValue (this); | ||||
| activeStreamLock.exit(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -205,9 +205,8 @@ public: | |||||
| if (callback_ != 0) | if (callback_ != 0) | ||||
| callback_->audioDeviceAboutToStart (this); | callback_->audioDeviceAboutToStart (this); | ||||
| callbackLock.enter(); | |||||
| const ScopedLock sl (callbackLock); | |||||
| callback = callback_; | callback = callback_; | ||||
| callbackLock.exit(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -215,10 +214,13 @@ public: | |||||
| { | { | ||||
| if (isRunning) | 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) | if (lastCallback != 0) | ||||
| lastCallback->audioDeviceStopped(); | lastCallback->audioDeviceStopped(); | ||||
| @@ -538,9 +538,10 @@ public: | |||||
| void stop (bool leaveInterruptRunning) | void stop (bool leaveInterruptRunning) | ||||
| { | { | ||||
| callbackLock.enter(); | |||||
| callback = 0; | |||||
| callbackLock.exit(); | |||||
| { | |||||
| const ScopedLock sl (callbackLock); | |||||
| callback = 0; | |||||
| } | |||||
| if (started | if (started | ||||
| && (deviceID != 0) | && (deviceID != 0) | ||||
| @@ -556,8 +557,7 @@ public: | |||||
| #endif | #endif | ||||
| started = false; | started = false; | ||||
| callbackLock.enter(); | |||||
| callbackLock.exit(); | |||||
| { const ScopedLock sl (callbackLock); } | |||||
| // wait until it's definately stopped calling back.. | // wait until it's definately stopped calling back.. | ||||
| for (int i = 40; --i >= 0;) | for (int i = 40; --i >= 0;) | ||||
| @@ -578,8 +578,7 @@ public: | |||||
| break; | break; | ||||
| } | } | ||||
| callbackLock.enter(); | |||||
| callbackLock.exit(); | |||||
| const ScopedLock sl (callbackLock); | |||||
| } | } | ||||
| if (inputDevice != 0) | if (inputDevice != 0) | ||||
| @@ -624,9 +624,10 @@ MidiInput::~MidiInput() | |||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | ||||
| mpc->active = false; | mpc->active = false; | ||||
| callbackLock.enter(); | |||||
| activeCallbacks.removeValue (mpc); | |||||
| callbackLock.exit(); | |||||
| { | |||||
| const ScopedLock sl (callbackLock); | |||||
| activeCallbacks.removeValue (mpc); | |||||
| } | |||||
| if (mpc->portAndEndpoint->port != 0) | if (mpc->portAndEndpoint->port != 0) | ||||
| OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); | OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); | ||||
| @@ -637,16 +638,14 @@ MidiInput::~MidiInput() | |||||
| void MidiInput::start() | void MidiInput::start() | ||||
| { | { | ||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | |||||
| const ScopedLock sl (callbackLock); | const ScopedLock sl (callbackLock); | ||||
| mpc->active = true; | |||||
| ((MidiPortAndCallback*) internal)->active = true; | |||||
| } | } | ||||
| void MidiInput::stop() | void MidiInput::stop() | ||||
| { | { | ||||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; | |||||
| const ScopedLock sl (callbackLock); | const ScopedLock sl (callbackLock); | ||||
| mpc->active = false; | |||||
| ((MidiPortAndCallback*) internal)->active = false; | |||||
| } | } | ||||
| #undef log | #undef log | ||||
| @@ -82,24 +82,25 @@ public: | |||||
| return; | return; | ||||
| const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte); | const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte); | ||||
| const double time = timeStampToTime (timeStamp); | 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(); | notify(); | ||||
| } | } | ||||
| @@ -111,22 +112,23 @@ public: | |||||
| { | { | ||||
| const double time = timeStampToTime (timeStamp); | 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(); | 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) | if (len == 0) | ||||
| { | { | ||||
| @@ -234,8 +238,7 @@ public: | |||||
| activeMidiThreads.removeValue (this); | activeMidiThreads.removeValue (this); | ||||
| lock.enter(); | |||||
| lock.exit(); | |||||
| { const ScopedLock sl (lock); } | |||||
| for (int i = numInHeaders; --i >= 0;) | for (int i = numInHeaders; --i >= 0;) | ||||
| { | { | ||||
| @@ -26,6 +26,9 @@ | |||||
| #ifndef __JUCE_CRITICALSECTION_JUCEHEADER__ | #ifndef __JUCE_CRITICALSECTION_JUCEHEADER__ | ||||
| #define __JUCE_CRITICALSECTION_JUCEHEADER__ | #define __JUCE_CRITICALSECTION_JUCEHEADER__ | ||||
| class JUCE_API ScopedLock; | |||||
| class JUCE_API ScopedUnlock; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** | /** | ||||
| @@ -84,6 +87,13 @@ public: | |||||
| void exit() const throw(); | 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 | juce_UseDebuggingNewOperator | ||||
| @@ -103,7 +113,7 @@ private: | |||||
| #endif | #endif | ||||
| CriticalSection (const CriticalSection&); | 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. | 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. | optimised out by the compiler. | ||||
| @see Array, OwnedArray, ReferenceCountedArray | @see Array, OwnedArray, ReferenceCountedArray | ||||
| @@ -124,6 +134,16 @@ public: | |||||
| inline void enter() const throw() {} | inline void enter() const throw() {} | ||||
| inline void exit() 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; | |||||
| }; | }; | ||||
| @@ -31,7 +31,6 @@ BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_Thread.h" | #include "juce_Thread.h" | ||||
| #include "juce_ScopedLock.h" | #include "juce_ScopedLock.h" | ||||
| #include "../core/juce_Time.h" | #include "../core/juce_Time.h" | ||||
| #include "../containers/juce_VoidArray.h" | |||||
| // these functions are implemented in the platform-specific code. | // these functions are implemented in the platform-specific code. | ||||
| void* juce_createThread (void* userData); | void* juce_createThread (void* userData); | ||||
| @@ -42,9 +41,6 @@ void juce_setCurrentThreadName (const String& name); | |||||
| void juce_CloseThreadHandle (void* handle); | void juce_CloseThreadHandle (void* handle); | ||||
| #endif | #endif | ||||
| //============================================================================== | |||||
| static VoidArray runningThreads; | |||||
| static CriticalSection runningThreadsLock; | |||||
| //============================================================================== | //============================================================================== | ||||
| void Thread::threadEntryPoint (Thread* const thread) | void Thread::threadEntryPoint (Thread* const thread) | ||||
| @@ -251,7 +247,7 @@ Thread* Thread::getCurrentThread() | |||||
| for (int i = runningThreads.size(); --i >= 0;) | for (int i = runningThreads.size(); --i >= 0;) | ||||
| { | { | ||||
| Thread* const t = (Thread*) runningThreads.getUnchecked(i); | |||||
| Thread* const t = runningThreads.getUnchecked(i); | |||||
| if (t->threadId_ == thisId) | if (t->threadId_ == thisId) | ||||
| return t; | return t; | ||||
| @@ -266,20 +262,27 @@ void Thread::stopAllThreads (const int timeOutMilliseconds) | |||||
| const ScopedLock sl (runningThreadsLock); | const ScopedLock sl (runningThreadsLock); | ||||
| for (int i = runningThreads.size(); --i >= 0;) | for (int i = runningThreads.size(); --i >= 0;) | ||||
| ((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit(); | |||||
| runningThreads.getUnchecked(i)->signalThreadShouldExit(); | |||||
| } | } | ||||
| for (;;) | 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; | break; | ||||
| t->stopThread (timeOutMilliseconds); | |||||
| firstThread->stopThread (timeOutMilliseconds); | |||||
| } | } | ||||
| } | } | ||||
| Array<Thread*> Thread::runningThreads; | |||||
| CriticalSection Thread::runningThreadsLock; | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -28,6 +28,7 @@ | |||||
| #include "juce_WaitableEvent.h" | #include "juce_WaitableEvent.h" | ||||
| #include "juce_CriticalSection.h" | #include "juce_CriticalSection.h" | ||||
| #include "../containers/juce_Array.h" | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -281,6 +282,8 @@ private: | |||||
| friend void JUCE_API juce_threadEntryPoint (void*); | friend void JUCE_API juce_threadEntryPoint (void*); | ||||
| static void threadEntryPoint (Thread* thread); | static void threadEntryPoint (Thread* thread); | ||||
| static Array<Thread*> runningThreads; | |||||
| static CriticalSection runningThreadsLock; | |||||
| Thread (const Thread&); | Thread (const Thread&); | ||||
| const Thread& operator= (const Thread&); | const Thread& operator= (const Thread&); | ||||
| @@ -221,9 +221,11 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job, | |||||
| const bool interruptIfRunning, | const bool interruptIfRunning, | ||||
| const int timeOutMs) | const int timeOutMs) | ||||
| { | { | ||||
| bool dontWait = true; | |||||
| if (job != 0) | if (job != 0) | ||||
| { | { | ||||
| lock.enter(); | |||||
| const ScopedLock sl (lock); | |||||
| if (jobs.contains (job)) | if (jobs.contains (job)) | ||||
| { | { | ||||
| @@ -232,20 +234,16 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job, | |||||
| if (interruptIfRunning) | if (interruptIfRunning) | ||||
| job->signalJobShouldExit(); | job->signalJobShouldExit(); | ||||
| lock.exit(); | |||||
| return waitForJobToFinish (job, timeOutMs); | |||||
| dontWait = false; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| jobs.removeValue (job); | jobs.removeValue (job); | ||||
| } | } | ||||
| } | } | ||||
| lock.exit(); | |||||
| } | } | ||||
| return true; | |||||
| return dontWait || waitForJobToFinish (job, timeOutMs); | |||||
| } | } | ||||
| bool ThreadPool::removeAllJobs (const bool interruptRunningJobs, | bool ThreadPool::removeAllJobs (const bool interruptRunningJobs, | ||||
| @@ -54,9 +54,12 @@ void DeletedAtShutdown::deleteAll() | |||||
| { | { | ||||
| // make a local copy of the array, so it can't get into a loop if something | // make a local copy of the array, so it can't get into a loop if something | ||||
| // creates another DeletedAtShutdown object during its destructor. | // 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;) | for (int i = localCopy.size(); --i >= 0;) | ||||
| { | { | ||||