From 7bfa419f178bbd20e3f10a23a50ab0fc3aa96f65 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Wed, 19 Jan 2011 18:15:24 +0000 Subject: [PATCH] Changed the return type of TimeSliceThreadClient::useTimeSlice(). --- juce_amalgamated.cpp | 170 ++++++++++-------- juce_amalgamated.h | 35 ++-- .../juce_AudioFormatWriter.cpp | 8 +- .../juce_AudioThumbnail.cpp | 37 ++-- src/core/juce_StandardHeader.h | 2 +- src/core/juce_TargetPlatform.h | 2 +- .../juce_DirectoryContentsList.cpp | 6 +- .../filebrowser/juce_DirectoryContentsList.h | 2 +- .../filebrowser/juce_FileListComponent.cpp | 4 +- .../filebrowser/juce_FileTreeComponent.cpp | 5 +- src/threads/juce_TimeSliceThread.cpp | 102 +++++++---- src/threads/juce_TimeSliceThread.h | 31 ++-- 12 files changed, 229 insertions(+), 175 deletions(-) diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 4611b70c17..b02bb1e9c7 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -176,7 +176,7 @@ #endif #endif - #if ! JUCE_VC7_OR_EARLIER + #if ! JUCE_VC7_OR_EARLIER && ! defined (__INTEL_COMPILER) #define JUCE_USE_INTRINSICS 1 #endif #else @@ -17363,9 +17363,7 @@ BEGIN_JUCE_NAMESPACE TimeSliceThread::TimeSliceThread (const String& threadName) : Thread (threadName), - index (0), - clientBeingCalled (0), - clientsChanged (false) + clientBeingCalled (0) { } @@ -17374,18 +17372,20 @@ TimeSliceThread::~TimeSliceThread() stopThread (2000); } -void TimeSliceThread::addTimeSliceClient (TimeSliceClient* const client) +void TimeSliceThread::addTimeSliceClient (TimeSliceClient* const client, int millisecondsBeforeStarting) { - const ScopedLock sl (listLock); - clients.addIfNotAlreadyThere (client); - clientsChanged = true; - notify(); + if (client != 0) + { + const ScopedLock sl (listLock); + client->nextCallTime = Time::getCurrentTime() + RelativeTime::milliseconds (millisecondsBeforeStarting); + clients.addIfNotAlreadyThere (client); + notify(); + } } void TimeSliceThread::removeTimeSliceClient (TimeSliceClient* const client) { const ScopedLock sl1 (listLock); - clientsChanged = true; // if there's a chance we're in the middle of calling this client, we need to // also lock the outer lock.. @@ -17415,52 +17415,76 @@ TimeSliceClient* TimeSliceThread::getClient (const int i) const return clients [i]; } +TimeSliceClient* TimeSliceThread::getNextClient (int index) const +{ + Time soonest; + TimeSliceClient* client = 0; + + for (int i = clients.size(); --i >= 0;) + { + TimeSliceClient* const c = clients.getUnchecked ((i + index) % clients.size()); + + if (client == 0 || c->nextCallTime < soonest) + { + client = c; + soonest = c->nextCallTime; + } + } + + return client; +} + void TimeSliceThread::run() { - int numCallsSinceBusy = 0; + int index = 0; while (! threadShouldExit()) { int timeToWait = 500; { - const ScopedLock sl (callbackLock); + Time nextClientTime; { const ScopedLock sl2 (listLock); - if (clients.size() > 0) - { - index = (index + 1) % clients.size(); + index = clients.size() > 0 ? ((index + 1) % clients.size()) : 0; - clientBeingCalled = clients [index]; - } - else - { - index = 0; - clientBeingCalled = 0; - } - - if (clientsChanged) - { - clientsChanged = false; - numCallsSinceBusy = 0; - } + TimeSliceClient* const firstClient = getNextClient (index); + if (firstClient != 0) + nextClientTime = firstClient->nextCallTime; } - if (clientBeingCalled != 0) - { - if (clientBeingCalled->useTimeSlice()) - numCallsSinceBusy = 0; - else - ++numCallsSinceBusy; + const Time now (Time::getCurrentTime()); - if (numCallsSinceBusy >= clients.size()) - timeToWait = 500; - else if (index == 0) - timeToWait = 1; // throw in an occasional pause, to stop everything locking up - else - timeToWait = 0; + if (nextClientTime > now) + { + timeToWait = (int) jmin ((int64) 500, (nextClientTime - now).inMilliseconds()); + } + else + { + timeToWait = index == 0 ? 1 : 0; + + const ScopedLock sl (callbackLock); + + { + const ScopedLock sl2 (listLock); + clientBeingCalled = getNextClient (index); + } + + if (clientBeingCalled != 0) + { + const int msUntilNextCall = clientBeingCalled->useTimeSlice(); + + const ScopedLock sl2 (listLock); + + if (msUntilNextCall >= 0) + clientBeingCalled->nextCallTime += RelativeTime::milliseconds (msUntilNextCall); + else + clients.removeValue (clientBeingCalled); + + clientBeingCalled = 0; + } } } @@ -21509,7 +21533,7 @@ public: isRunning = false; timeSliceThread.removeTimeSliceClient (this); - while (useTimeSlice()) + while (useTimeSlice() == 0) {} } @@ -21537,7 +21561,7 @@ public: return true; } - bool useTimeSlice() + int useTimeSlice() { const int numToDo = getTotalSize() / 4; @@ -21545,7 +21569,7 @@ public: prepareToRead (numToDo, start1, size1, start2, size2); if (size1 <= 0) - return false; + return 10; writer->writeFromAudioSampleBuffer (buffer, start1, size1); @@ -21566,7 +21590,7 @@ public: } finishedRead (size1 + size2); - return true; + return 0; } void setThumbnail (AudioThumbnail* thumb) @@ -21913,8 +21937,7 @@ struct AudioThumbnail::MinMaxValue } }; -class AudioThumbnail::LevelDataSource : public TimeSliceClient, - public Timer +class AudioThumbnail::LevelDataSource : public TimeSliceClient { public: LevelDataSource (AudioThumbnail& owner_, AudioFormatReader* newReader, int64 hash) @@ -21934,7 +21957,7 @@ public: owner.cache.removeTimeSliceClient (this); } - enum { timeBeforeDeletingReader = 2000 }; + enum { timeBeforeDeletingReader = 1000 }; void initialise (int64 numSamplesFinished_) { @@ -21950,9 +21973,9 @@ public: numChannels = reader->numChannels; sampleRate = reader->sampleRate; - if (lengthInSamples <= 0) + if (lengthInSamples <= 0 || isFullyLoaded()) reader = 0; - else if (! isFullyLoaded()) + else owner.cache.addTimeSliceClient (this); } } @@ -21960,7 +21983,14 @@ public: void getLevels (int64 startSample, int numSamples, Array& levels) { const ScopedLock sl (readerLock); - createReader(); + + if (reader == 0) + { + createReader(); + + if (reader != 0) + owner.cache.addTimeSliceClient (this); + } if (reader != 0) { @@ -21978,19 +22008,16 @@ public: reader = 0; } - bool useTimeSlice() + int useTimeSlice() { if (isFullyLoaded()) { if (reader != 0 && source != 0) - startTimer (timeBeforeDeletingReader); + releaseResources(); - owner.cache.removeTimeSliceClient (this); - return false; + return -1; } - stopTimer(); - bool justFinished = false; { @@ -22001,7 +22028,7 @@ public: if (reader != 0) { if (! readNextBlock()) - return true; + return 0; justFinished = true; } @@ -22010,13 +22037,7 @@ public: if (justFinished) owner.cache.storeThumb (owner, hashCode); - return false; - } - - void timerCallback() - { - stopTimer(); - releaseResources(); + return timeBeforeDeletingReader; } bool isFullyLoaded() const throw() @@ -57840,7 +57861,7 @@ void DirectoryContentsList::changed() sendChangeMessage(); } -bool DirectoryContentsList::useTimeSlice() +int DirectoryContentsList::useTimeSlice() { const uint32 startTime = Time::getApproximateMillisecondCounter(); bool hasChanged = false; @@ -57852,7 +57873,7 @@ bool DirectoryContentsList::useTimeSlice() if (hasChanged) changed(); - return false; + return 500; } if (shouldStop || (Time::getApproximateMillisecondCounter() > startTime + 150)) @@ -57862,7 +57883,7 @@ bool DirectoryContentsList::useTimeSlice() if (hasChanged) changed(); - return true; + return 0; } bool DirectoryContentsList::checkNextFile (bool& hasChanged) @@ -58957,10 +58978,10 @@ public: } } - bool useTimeSlice() + int useTimeSlice() { updateIcon (false); - return false; + return -1; } void handleAsyncUpdate() @@ -59655,11 +59676,10 @@ public: owner.sendSelectionChangeMessage(); } - bool useTimeSlice() + int useTimeSlice() { updateIcon (false); - thread.removeTimeSliceClient (this); - return false; + return -1; } void handleAsyncUpdate() @@ -61201,7 +61221,7 @@ public: component->setVisible (! useProxyComponent); } - bool useTimeslice (const int elapsed) + int useTimeslice (const int elapsed) { Component* const c = proxy != 0 ? static_cast (proxy) : static_cast (component); @@ -61249,13 +61269,13 @@ public: } if (stillBusy) - return true; + return 0; } } } moveToFinalDestination(); - return false; + return -1; } void moveToFinalDestination() diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 97c02561b6..c162ac7e13 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 15 +#define JUCE_BUILDNUMBER 16 /** Current Juce version number. @@ -223,7 +223,7 @@ namespace JuceDummyNamespace {} #endif #endif - #if ! JUCE_VC7_OR_EARLIER + #if ! JUCE_VC7_OR_EARLIER && ! defined (__INTEL_COMPILER) #define JUCE_USE_INTRINSICS 1 #endif #else @@ -19825,6 +19825,8 @@ private: #ifndef __JUCE_TIMESLICETHREAD_JUCEHEADER__ #define __JUCE_TIMESLICETHREAD_JUCEHEADER__ +class TimeSliceThread; + /** Used by the TimeSliceThread class. @@ -19850,13 +19852,18 @@ public: The implementation of this method should use its time-slice to do something that's quick - never block for longer than absolutely necessary. - @returns Your method should return true if it needs more time, or false if it's - not too busy and doesn't need calling back urgently. If all the thread's - clients indicate that they're not busy, then it'll save CPU by sleeping for - up to half a second in between callbacks. You can force the TimeSliceThread - to wake up and poll again immediately by calling its notify() method. + @returns Your method should return the number of milliseconds which it would like to wait before being called + again. Returning 0 will make the thread call again as soon as possible (after possibly servicing + other busy clients). If you return a value below zero, your client will be removed from the list of clients, + and won't be called again. The value you specify isn't a guaranteee, and is only used as a hint by the + thread - the actual time before the next callback may be more or less than specified. + You can force the TimeSliceThread to wake up and poll again immediately by calling its notify() method. */ - virtual bool useTimeSlice() = 0; + virtual int useTimeSlice() = 0; + +private: + friend class TimeSliceThread; + Time nextCallTime; }; /** @@ -19888,10 +19895,10 @@ public: /** Adds a client to the list. - The client's callbacks will start immediately (possibly before the method - has returned). + The client's callbacks will start after the number of milliseconds specified + by millisecondsBeforeStarting (and this may happen before this method has returned). */ - void addTimeSliceClient (TimeSliceClient* client); + void addTimeSliceClient (TimeSliceClient* client, int millisecondsBeforeStarting = 0); /** Removes a client from the list. @@ -19912,9 +19919,9 @@ public: private: CriticalSection callbackLock, listLock; Array clients; - int index; TimeSliceClient* clientBeingCalled; - bool clientsChanged; + + TimeSliceClient* getNextClient (int index) const; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimeSliceThread); }; @@ -51277,7 +51284,7 @@ public: const FileFilter* getFilter() const { return fileFilter; } /** @internal */ - bool useTimeSlice(); + int useTimeSlice(); /** @internal */ TimeSliceThread& getTimeSliceThread() { return thread; } /** @internal */ diff --git a/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp b/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp index 78302f918f..bc3d43c731 100644 --- a/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp +++ b/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp @@ -201,7 +201,7 @@ public: isRunning = false; timeSliceThread.removeTimeSliceClient (this); - while (useTimeSlice()) + while (useTimeSlice() == 0) {} } @@ -229,7 +229,7 @@ public: return true; } - bool useTimeSlice() + int useTimeSlice() { const int numToDo = getTotalSize() / 4; @@ -237,7 +237,7 @@ public: prepareToRead (numToDo, start1, size1, start2, size2); if (size1 <= 0) - return false; + return 10; writer->writeFromAudioSampleBuffer (buffer, start1, size1); @@ -258,7 +258,7 @@ public: } finishedRead (size1 + size2); - return true; + return 0; } void setThumbnail (AudioThumbnail* thumb) diff --git a/src/audio/audio_file_formats/juce_AudioThumbnail.cpp b/src/audio/audio_file_formats/juce_AudioThumbnail.cpp index 23fd0d6a99..4b78564984 100644 --- a/src/audio/audio_file_formats/juce_AudioThumbnail.cpp +++ b/src/audio/audio_file_formats/juce_AudioThumbnail.cpp @@ -82,8 +82,7 @@ struct AudioThumbnail::MinMaxValue }; //============================================================================== -class AudioThumbnail::LevelDataSource : public TimeSliceClient, - public Timer +class AudioThumbnail::LevelDataSource : public TimeSliceClient { public: LevelDataSource (AudioThumbnail& owner_, AudioFormatReader* newReader, int64 hash) @@ -103,7 +102,7 @@ public: owner.cache.removeTimeSliceClient (this); } - enum { timeBeforeDeletingReader = 2000 }; + enum { timeBeforeDeletingReader = 1000 }; void initialise (int64 numSamplesFinished_) { @@ -119,9 +118,9 @@ public: numChannels = reader->numChannels; sampleRate = reader->sampleRate; - if (lengthInSamples <= 0) + if (lengthInSamples <= 0 || isFullyLoaded()) reader = 0; - else if (! isFullyLoaded()) + else owner.cache.addTimeSliceClient (this); } } @@ -129,7 +128,14 @@ public: void getLevels (int64 startSample, int numSamples, Array& levels) { const ScopedLock sl (readerLock); - createReader(); + + if (reader == 0) + { + createReader(); + + if (reader != 0) + owner.cache.addTimeSliceClient (this); + } if (reader != 0) { @@ -147,19 +153,16 @@ public: reader = 0; } - bool useTimeSlice() + int useTimeSlice() { if (isFullyLoaded()) { if (reader != 0 && source != 0) - startTimer (timeBeforeDeletingReader); + releaseResources(); - owner.cache.removeTimeSliceClient (this); - return false; + return -1; } - stopTimer(); - bool justFinished = false; { @@ -170,7 +173,7 @@ public: if (reader != 0) { if (! readNextBlock()) - return true; + return 0; justFinished = true; } @@ -179,13 +182,7 @@ public: if (justFinished) owner.cache.storeThumb (owner, hashCode); - return false; - } - - void timerCallback() - { - stopTimer(); - releaseResources(); + return timeBeforeDeletingReader; } bool isFullyLoaded() const throw() diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index a65aaa57f2..f1205ad7ae 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 15 +#define JUCE_BUILDNUMBER 16 /** Current Juce version number. diff --git a/src/core/juce_TargetPlatform.h b/src/core/juce_TargetPlatform.h index 309b543e6b..c81a3697c2 100644 --- a/src/core/juce_TargetPlatform.h +++ b/src/core/juce_TargetPlatform.h @@ -166,7 +166,7 @@ #endif #endif - #if ! JUCE_VC7_OR_EARLIER + #if ! JUCE_VC7_OR_EARLIER && ! defined (__INTEL_COMPILER) #define JUCE_USE_INTRINSICS 1 #endif #else diff --git a/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp b/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp index e33cda78ee..ea3f434369 100644 --- a/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp +++ b/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp @@ -165,7 +165,7 @@ void DirectoryContentsList::changed() } //============================================================================== -bool DirectoryContentsList::useTimeSlice() +int DirectoryContentsList::useTimeSlice() { const uint32 startTime = Time::getApproximateMillisecondCounter(); bool hasChanged = false; @@ -177,7 +177,7 @@ bool DirectoryContentsList::useTimeSlice() if (hasChanged) changed(); - return false; + return 500; } if (shouldStop || (Time::getApproximateMillisecondCounter() > startTime + 150)) @@ -187,7 +187,7 @@ bool DirectoryContentsList::useTimeSlice() if (hasChanged) changed(); - return true; + return 0; } bool DirectoryContentsList::checkNextFile (bool& hasChanged) diff --git a/src/gui/components/filebrowser/juce_DirectoryContentsList.h b/src/gui/components/filebrowser/juce_DirectoryContentsList.h index 08d4291ed5..cc02062638 100644 --- a/src/gui/components/filebrowser/juce_DirectoryContentsList.h +++ b/src/gui/components/filebrowser/juce_DirectoryContentsList.h @@ -185,7 +185,7 @@ public: //============================================================================== /** @internal */ - bool useTimeSlice(); + int useTimeSlice(); /** @internal */ TimeSliceThread& getTimeSliceThread() { return thread; } /** @internal */ diff --git a/src/gui/components/filebrowser/juce_FileListComponent.cpp b/src/gui/components/filebrowser/juce_FileListComponent.cpp index 002f74d525..a76dc581c6 100644 --- a/src/gui/components/filebrowser/juce_FileListComponent.cpp +++ b/src/gui/components/filebrowser/juce_FileListComponent.cpp @@ -165,10 +165,10 @@ public: } } - bool useTimeSlice() + int useTimeSlice() { updateIcon (false); - return false; + return -1; } void handleAsyncUpdate() diff --git a/src/gui/components/filebrowser/juce_FileTreeComponent.cpp b/src/gui/components/filebrowser/juce_FileTreeComponent.cpp index abd0bb111f..318fd38d1a 100644 --- a/src/gui/components/filebrowser/juce_FileTreeComponent.cpp +++ b/src/gui/components/filebrowser/juce_FileTreeComponent.cpp @@ -173,11 +173,10 @@ public: owner.sendSelectionChangeMessage(); } - bool useTimeSlice() + int useTimeSlice() { updateIcon (false); - thread.removeTimeSliceClient (this); - return false; + return -1; } void handleAsyncUpdate() diff --git a/src/threads/juce_TimeSliceThread.cpp b/src/threads/juce_TimeSliceThread.cpp index 49a537fba6..492af400fa 100644 --- a/src/threads/juce_TimeSliceThread.cpp +++ b/src/threads/juce_TimeSliceThread.cpp @@ -34,9 +34,7 @@ BEGIN_JUCE_NAMESPACE //============================================================================== TimeSliceThread::TimeSliceThread (const String& threadName) : Thread (threadName), - index (0), - clientBeingCalled (0), - clientsChanged (false) + clientBeingCalled (0) { } @@ -46,18 +44,20 @@ TimeSliceThread::~TimeSliceThread() } //============================================================================== -void TimeSliceThread::addTimeSliceClient (TimeSliceClient* const client) +void TimeSliceThread::addTimeSliceClient (TimeSliceClient* const client, int millisecondsBeforeStarting) { - const ScopedLock sl (listLock); - clients.addIfNotAlreadyThere (client); - clientsChanged = true; - notify(); + if (client != 0) + { + const ScopedLock sl (listLock); + client->nextCallTime = Time::getCurrentTime() + RelativeTime::milliseconds (millisecondsBeforeStarting); + clients.addIfNotAlreadyThere (client); + notify(); + } } void TimeSliceThread::removeTimeSliceClient (TimeSliceClient* const client) { const ScopedLock sl1 (listLock); - clientsChanged = true; // if there's a chance we're in the middle of calling this client, we need to // also lock the outer lock.. @@ -88,52 +88,76 @@ TimeSliceClient* TimeSliceThread::getClient (const int i) const } //============================================================================== +TimeSliceClient* TimeSliceThread::getNextClient (int index) const +{ + Time soonest; + TimeSliceClient* client = 0; + + for (int i = clients.size(); --i >= 0;) + { + TimeSliceClient* const c = clients.getUnchecked ((i + index) % clients.size()); + + if (client == 0 || c->nextCallTime < soonest) + { + client = c; + soonest = c->nextCallTime; + } + } + + return client; +} + void TimeSliceThread::run() { - int numCallsSinceBusy = 0; + int index = 0; while (! threadShouldExit()) { int timeToWait = 500; { - const ScopedLock sl (callbackLock); + Time nextClientTime; { const ScopedLock sl2 (listLock); - if (clients.size() > 0) - { - index = (index + 1) % clients.size(); + index = clients.size() > 0 ? ((index + 1) % clients.size()) : 0; - clientBeingCalled = clients [index]; - } - else - { - index = 0; - clientBeingCalled = 0; - } - - if (clientsChanged) - { - clientsChanged = false; - numCallsSinceBusy = 0; - } + TimeSliceClient* const firstClient = getNextClient (index); + if (firstClient != 0) + nextClientTime = firstClient->nextCallTime; } - if (clientBeingCalled != 0) - { - if (clientBeingCalled->useTimeSlice()) - numCallsSinceBusy = 0; - else - ++numCallsSinceBusy; + const Time now (Time::getCurrentTime()); - if (numCallsSinceBusy >= clients.size()) - timeToWait = 500; - else if (index == 0) - timeToWait = 1; // throw in an occasional pause, to stop everything locking up - else - timeToWait = 0; + if (nextClientTime > now) + { + timeToWait = (int) jmin ((int64) 500, (nextClientTime - now).inMilliseconds()); + } + else + { + timeToWait = index == 0 ? 1 : 0; + + const ScopedLock sl (callbackLock); + + { + const ScopedLock sl2 (listLock); + clientBeingCalled = getNextClient (index); + } + + if (clientBeingCalled != 0) + { + const int msUntilNextCall = clientBeingCalled->useTimeSlice(); + + const ScopedLock sl2 (listLock); + + if (msUntilNextCall >= 0) + clientBeingCalled->nextCallTime += RelativeTime::milliseconds (msUntilNextCall); + else + clients.removeValue (clientBeingCalled); + + clientBeingCalled = 0; + } } } diff --git a/src/threads/juce_TimeSliceThread.h b/src/threads/juce_TimeSliceThread.h index 0540fd5a74..28885bcec3 100644 --- a/src/threads/juce_TimeSliceThread.h +++ b/src/threads/juce_TimeSliceThread.h @@ -28,7 +28,8 @@ #include "juce_Thread.h" #include "../containers/juce_Array.h" - +#include "../core/juce_Time.h" +class TimeSliceThread; //============================================================================== /** @@ -56,13 +57,19 @@ public: The implementation of this method should use its time-slice to do something that's quick - never block for longer than absolutely necessary. - @returns Your method should return true if it needs more time, or false if it's - not too busy and doesn't need calling back urgently. If all the thread's - clients indicate that they're not busy, then it'll save CPU by sleeping for - up to half a second in between callbacks. You can force the TimeSliceThread - to wake up and poll again immediately by calling its notify() method. + @returns Your method should return the number of milliseconds which it would like to wait before being called + again. Returning 0 will make the thread call again as soon as possible (after possibly servicing + other busy clients). If you return a value below zero, your client will be removed from the list of clients, + and won't be called again. The value you specify isn't a guaranteee, and is only used as a hint by the + thread - the actual time before the next callback may be more or less than specified. + You can force the TimeSliceThread to wake up and poll again immediately by calling its notify() method. */ - virtual bool useTimeSlice() = 0; + virtual int useTimeSlice() = 0; + + +private: + friend class TimeSliceThread; + Time nextCallTime; }; @@ -97,10 +104,10 @@ public: //============================================================================== /** Adds a client to the list. - The client's callbacks will start immediately (possibly before the method - has returned). + The client's callbacks will start after the number of milliseconds specified + by millisecondsBeforeStarting (and this may happen before this method has returned). */ - void addTimeSliceClient (TimeSliceClient* client); + void addTimeSliceClient (TimeSliceClient* client, int millisecondsBeforeStarting = 0); /** Removes a client from the list. @@ -123,9 +130,9 @@ public: private: CriticalSection callbackLock, listLock; Array clients; - int index; TimeSliceClient* clientBeingCalled; - bool clientsChanged; + + TimeSliceClient* getNextClient (int index) const; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimeSliceThread); };