Browse Source

Modernised some old code.

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

+ 268
- 218
juce_amalgamated.cpp View File

@@ -5417,18 +5417,16 @@ void juce_CheckForDanglingStreams()
OutputStream::OutputStream() throw() 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


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


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

@@ -128,11 +128,12 @@ void AudioTransportSource::start()
{ {
if ((! playing) && masterSource != 0) 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)


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

@@ -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)
{ {


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

@@ -49,10 +49,14 @@ void MixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhen
{ {
if (input != 0 && ! inputs.contains (input)) 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])


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

@@ -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;


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

@@ -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)


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

@@ -114,9 +114,12 @@ void AudioProcessor::sendParamChangeMessageToListeners (const int parameterIndex
for (int i = listeners.size(); --i >= 0;) 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);


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

@@ -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();


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

@@ -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


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

@@ -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;
//============================================================================== //==============================================================================


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

@@ -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;
//============================================================================== //==============================================================================


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

@@ -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;
//============================================================================== //==============================================================================


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

@@ -229,28 +229,27 @@ bool MessageManager::currentThreadHasLockedMessageManager() const throw()
accessed from another thread inside a MM lock, you're screwed. (this is exactly what happens 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();
}
} }
} }


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

@@ -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&);
}; };


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

@@ -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)
{ {


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

@@ -1168,16 +1168,19 @@ void TreeViewItem::addSubItem (TreeViewItem* const newItem, const int insertPosi
void TreeViewItem::removeSubItem (const int index, const bool deleteItem) 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()


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

@@ -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
} }


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

@@ -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();


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

@@ -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)


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

@@ -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


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

@@ -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;)
{ {


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

@@ -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;
}; };


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

@@ -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

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

@@ -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&);


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

@@ -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,


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

@@ -54,9 +54,12 @@ void DeletedAtShutdown::deleteAll()
{ {
// make a local copy of the array, so it can't get into a loop if something // 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;)
{ {


Loading…
Cancel
Save