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