27 : threadName (name), threadStackSize (stackSize)
33 if (deleteOnThreadEnd)
53 CurrentThreadHolder() noexcept {}
58 JUCE_DECLARE_NON_COPYABLE (CurrentThreadHolder)
61 static char currentThreadHolderLock [
sizeof (
SpinLock)];
63 static SpinLock* castToSpinLockWithoutAliasingWarning (
void* s)
73 if (currentThreadHolder ==
nullptr)
74 currentThreadHolder =
new CurrentThreadHolder();
76 return currentThreadHolder;
79 void Thread::threadEntryPoint()
82 currentThreadHolder->value =
this;
84 if (threadName.isNotEmpty())
87 if (startSuspensionEvent.wait (10000))
91 if (affinityMask != 0)
104 currentThreadHolder->value.releaseCurrentThreadStorage();
108 auto shouldDeleteThis = deleteOnThreadEnd;
111 if (shouldDeleteThis)
116 void JUCE_API juce_threadEntryPoint (
void* userData)
118 static_cast<Thread*
> (userData)->threadEntryPoint();
128 if (threadHandle.get() ==
nullptr)
131 setThreadPriority (threadHandle.get(), threadPriority);
132 startSuspensionEvent.signal();
140 if (threadHandle.get() ==
nullptr)
142 auto isRealtime = (priority == realtimeAudioPriority);
145 isAndroidRealtimeThread = isRealtime;
151 threadPriority = priority;
162 return threadHandle.get() !=
nullptr;
167 return getCurrentThreadHolder()->value.
get();
172 return threadId.get();
184 return shouldExit.get() != 0;
190 return currentThread->threadShouldExit();
226 if (timeOutMilliseconds != 0)
238 threadHandle =
nullptr;
249 listeners.add (listener);
254 listeners.remove (listener);
260 bool isRealtime = (newPriority == realtimeAudioPriority);
275 jassert (
isThreadRunning() && (isRealtime == isAndroidRealtimeThread));
277 isAndroidRealtimeThread = isRealtime;
280 if ((!
isThreadRunning()) || setThreadPriority (threadHandle.get(), newPriority))
282 threadPriority = newPriority;
291 return setThreadPriority ({}, newPriority);
296 affinityMask = newAffinityMask;
302 return defaultEvent.wait (timeOutMilliseconds);
307 defaultEvent.signal();
311 struct LambdaThread :
public Thread 313 LambdaThread (std::function<
void()> f) :
Thread (
"anonymous"), fn (f) {}
321 std::function<void()> fn;
323 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LambdaThread)
328 auto anon =
new LambdaThread (functionToRun);
329 anon->deleteOnThreadEnd =
true;
338 for (
int i = 20; --i >= 0;)
350 return juce_isRunningUnderDebugger();
362 :
UnitTest (
"Atomics", UnitTestCategories::threads)
365 void runTest()
override 370 expect (numElementsInArray(a1) == 7);
372 expect (numElementsInArray(a2) == 3);
376 expect (
ByteOrder::swap ((uint64) 0x1122334455667788ULL) == 0x8877665544332211LL);
378 beginTest (
"Atomic int");
379 AtomicTester <int>::testInteger (*this);
380 beginTest (
"Atomic unsigned int");
381 AtomicTester <unsigned int>::testInteger (*this);
382 beginTest (
"Atomic int32");
383 AtomicTester <int32>::testInteger (*this);
384 beginTest (
"Atomic uint32");
385 AtomicTester <uint32>::testInteger (*this);
386 beginTest (
"Atomic long");
387 AtomicTester <long>::testInteger (*this);
388 beginTest (
"Atomic int*");
389 AtomicTester <int*>::testInteger (*this);
390 beginTest (
"Atomic float");
391 AtomicTester <float>::testFloat (*this);
392 #if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms 393 beginTest (
"Atomic int64");
394 AtomicTester <int64>::testInteger (*this);
395 beginTest (
"Atomic uint64");
396 AtomicTester <uint64>::testInteger (*this);
397 beginTest (
"Atomic double");
398 AtomicTester <double>::testFloat (*this);
400 beginTest (
"Atomic pointer increment/decrement");
405 beginTest (
"Atomic void*");
409 atomic.
set ((
void*) 10);
412 expect (atomic.
value == c);
413 expect (atomic.
get() == c);
417 template <
typename Type>
423 static void testInteger (
UnitTest& test)
455 static void testFloat (
UnitTest& test)
479 static AtomicTests atomicUnitTests;
482 class ThreadLocalValueUnitTest :
public UnitTest,
486 ThreadLocalValueUnitTest()
487 :
UnitTest (
"ThreadLocalValue", UnitTestCategories::threads),
488 Thread (
"ThreadLocalValue Thread")
491 void runTest()
override 493 beginTest (
"values are thread local");
498 sharedThreadLocal = &threadLocal;
500 sharedThreadLocal.
get()->get() = 1;
506 mainThreadResult = sharedThreadLocal.get()->get();
508 expectEquals (mainThreadResult.get(), 1);
509 expectEquals (auxThreadResult.get(), 2);
512 beginTest (
"values are per-instance");
520 expectEquals (a.
get(), 1);
521 expectEquals (b.
get(), 2);
531 sharedThreadLocal.
get()->get() = 2;
532 auxThreadResult = sharedThreadLocal.
get()->get();
536 ThreadLocalValueUnitTest threadLocalValueUnitTest;
bool stopThread(int timeOutMilliseconds)
void addListener(Listener *)
static void launch(std::function< void()> functionToRun)
void set(Type newValue) noexcept
Thread(const String &threadName, size_t threadStackSize=0)
void signalThreadShouldExit()
static bool currentThreadShouldExit()
void setAffinityMask(uint32 affinityMask)
static void JUCE_CALLTYPE yield()
ThreadID getThreadId() const noexcept
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
std::atomic< Type > value
void enter() const noexcept
static JUCE_CONSTEXPR uint16 swap(uint16 value) noexcept
bool threadShouldExit() const
ReferencedType * get() const noexcept
Type exchange(Type newValue) noexcept
bool setPriority(int priority)
void expect(bool testResult, const String &failureMessage=String())
static void JUCE_CALLTYPE writeToLog(const String &message)
void memoryBarrier() noexcept
virtual void exitSignalSent()=0
bool waitForThreadToExit(int timeOutMilliseconds) const
Type get() const noexcept
bool isThreadRunning() const
Type & get() const noexcept
bool compareAndSetBool(Type newValue, Type valueToCompare) noexcept
static void JUCE_CALLTYPE setCurrentThreadAffinityMask(uint32 affinityMask)
static void JUCE_CALLTYPE sleep(int milliseconds)
static Thread *JUCE_CALLTYPE getCurrentThread()
static bool setCurrentThreadPriority(int priority)
static bool JUCE_CALLTYPE isRunningUnderDebugger() noexcept
bool wait(int timeOutMilliseconds) const
void removeListener(Listener *)
static uint32 getMillisecondCounter() noexcept
static void JUCE_CALLTYPE setCurrentThreadName(const String &newThreadName)