14 #pragma warning (push)
15 #pragma warning (disable: 4127)
18namespace tracktion {
inline namespace graph
25 constexpr int timeOutMilliseconds = -1;
33 __asm__ __volatile__ (
"yield");
34 __asm__ __volatile__ (
"yield");
51 if (threads.
size() == numThreads)
55 workgroup = workgroupToUse;
61 for (
size_t i = 0; i < numThreads; ++i)
64 setThreadPriority (threads.
back(), 10);
73 for (
auto& t : threads)
89 void signal (
int numToSignal)
override
96 for (
int i =
std::min ((
int) threads.
size(), numToSignal); --i >= 0;)
117 if (timeOutMilliseconds < 0)
124 [
this] { return ! shouldWait(); }))
150 bool shouldWaitOrIsNotTriggered()
161 workgroup.
join (token);
186 if (threads.
size() == numThreads)
190 workgroup = workgroupToUse;
196 for (
size_t i = 0; i < numThreads; ++i)
199 setThreadPriority (threads.
back(), 10);
208 for (
auto& t : threads)
230 thread_local int pauseCount = 0;
238 else if (pauseCount < 100)
240 else if (pauseCount < 150)
242 else if (pauseCount < 200)
265 workgroup.
join (token);
283 __asm__ __volatile__ (
"yield");
284 __asm__ __volatile__ (
"yield");
301 if (threads.
size() == numThreads)
305 workgroup = workgroupToUse;
311 for (
size_t i = 0; i < numThreads; ++i)
314 setThreadPriority (threads.
back(), 10);
323 for (
auto& t : threads)
346 for (
int i =
std::min ((
int) threads.
size(), numToSignal); --i >= 0;)
362 thread_local int pauseCount = 0;
375 else if (pauseCount < 50)
386 if (timeOutMilliseconds < 0)
388 condition.
wait (lock, [
this] {
return ! shouldWaitOrIsNotTriggered(); });
393 [
this] { return ! shouldWaitOrIsNotTriggered(); }))
419 bool shouldWaitOrIsNotTriggered()
430 workgroup.
join (token);
446template<
typename SemaphoreType>
456 if (threads.
size() == numThreads)
461 workgroup = workgroupToUse;
467 for (
size_t i = 0; i < numThreads; ++i)
470 setThreadPriority (threads.
back(), 10);
479 for (
auto& t : threads)
488 if (semaphore) semaphore->signal();
493 if (semaphore) semaphore->signal (
std::min (numToSignal, (
int) threads.
size()));
498 if (semaphore) semaphore->signal ((
int) threads.
size());
506 if (timeOutMilliseconds < 0)
537 workgroup.
join (token);
553template<
typename SemaphoreType>
563 if (threads.
size() == numThreads)
568 workgroup = workgroupToUse;
574 for (
size_t i = 0; i < numThreads; ++i)
577 setThreadPriority (threads.
back(), 10);
586 for (
auto& t : threads)
610 thread_local int pauseCount = 0;
623 else if (pauseCount < 50)
632 if (timeOutMilliseconds < 0)
669 workgroup.
join (token);
689 case ThreadPoolStrategy::conditionVariable:
691 case ThreadPoolStrategy::hybrid:
693 case ThreadPoolStrategy::semaphore:
695 case ThreadPoolStrategy::lightweightSemaphore:
697 case ThreadPoolStrategy::lightweightSemHybrid:
699 case ThreadPoolStrategy::realTime:
707 #pragma warning (pop)
void join(WorkgroupToken &token) const
static void JUCE_CALLTYPE disableDenormalisedNumberSupport(bool shouldDisable=true) noexcept
Plays back a node with mutiple threads.
int getBlockSize() const
Returns the current block size.
double getSampleRate() const
Returns the current sample rate.
T emplace_back(T... args)
LockFreeMultiThreadedNodePlayer::ThreadPoolCreator getPoolCreatorFunction(ThreadPoolStrategy poolType)
Returns a function to create a ThreadPool for the given stategy.
ThreadPoolStrategy
Available strategies for thread pools.
@ semaphore
Uses a semaphore to suspend threads.
bool tryToUpgradeCurrentThreadToRealtime(const juce::Thread::RealtimeOptions &)
Tries to upgrade the current thread to realtime priority.
RealtimeOptions withApproximateAudioProcessingTime(int samplesPerFrame, double sampleRate) const
RealtimeOptions withPriority(int newPriority) const
Base class for thread pools which can be customised to determine how cooperative threads should behav...
bool shouldWait()
Returns true if there are no free Nodes to be processed and the calling thread should wait until ther...
void signalShouldExit()
Signals the pool that all the threads should exit.
bool isFinalNodeReady()
Returns true if all the Nodes have been processed.
bool process()
Process the next chain of Nodes.
void resetExitSignal()
Signals the pool that all the threads should continue to run and not exit.
ThreadPool(LockFreeMultiThreadedNodePlayer &p)
Constructs a ThreadPool for a given LockFreeMultiThreadedNodePlayer.
bool shouldExit() const
Returns true if all the threads should exit.
void clearThreads() override
Subclasses should implement this to clear all the threads.
void signal(int numToSignal) override
Called by the player when more than one Node becomes available to process.
void createThreads(size_t numThreads, juce::AudioWorkgroup workgroupToUse) override
Subclasses should implement this to create the given number of threads.
void signalOne() override
Called by the player when a Node becomes available to process.
void waitForFinalNode() override
Called by the player when the audio thread has no free Nodes to process.
void signalAll() override
Called by the player when more than one Node becomes available to process.
void signalAll() override
Called by the player when more than one Node becomes available to process.
void signalOne() override
Called by the player when a Node becomes available to process.
void waitForFinalNode() override
Called by the player when the audio thread has no free Nodes to process.
void clearThreads() override
Subclasses should implement this to clear all the threads.
void signal(int numToSignal) override
Called by the player when more than one Node becomes available to process.
void createThreads(size_t numThreads, juce::AudioWorkgroup workgroupToUse) override
Subclasses should implement this to create the given number of threads.
void clearThreads() override
Subclasses should implement this to clear all the threads.
void signal(int) override
Called by the player when more than one Node becomes available to process.
void signalAll() override
Called by the player when more than one Node becomes available to process.
void createThreads(size_t numThreads, juce::AudioWorkgroup workgroupToUse) override
Subclasses should implement this to create the given number of threads.
void waitForFinalNode() override
Called by the player when the audio thread has no free Nodes to process.
void signalOne() override
Called by the player when a Node becomes available to process.
void signalAll() override
Called by the player when more than one Node becomes available to process.
void createThreads(size_t numThreads, juce::AudioWorkgroup workgroupToUse) override
Subclasses should implement this to create the given number of threads.
void waitForFinalNode() override
Called by the player when the audio thread has no free Nodes to process.
void signal(int numToSignal) override
Called by the player when more than one Node becomes available to process.
void clearThreads() override
Subclasses should implement this to clear all the threads.
void signalOne() override
Called by the player when a Node becomes available to process.
void clearThreads() override
Subclasses should implement this to clear all the threads.
void waitForFinalNode() override
Called by the player when the audio thread has no free Nodes to process.
void createThreads(size_t numThreads, juce::AudioWorkgroup workgroupToUse) override
Subclasses should implement this to create the given number of threads.
void signal(int numToSignal) override
Called by the player when more than one Node becomes available to process.
void signalOne() override
Called by the player when a Node becomes available to process.
void signalAll() override
Called by the player when more than one Node becomes available to process.