27 : threadName (name), threadStackSize (stackSize)
33 if (deleteOnThreadEnd)
61 static char currentThreadHolderLock [
sizeof (
SpinLock)];
63 static SpinLock* castToSpinLockWithoutAliasingWarning (
void* s)
68 static CurrentThreadHolder::Ptr getCurrentThreadHolder()
70 static CurrentThreadHolder::Ptr currentThreadHolder;
73 if (currentThreadHolder ==
nullptr)
74 currentThreadHolder =
new CurrentThreadHolder();
76 return currentThreadHolder;
79 void Thread::threadEntryPoint()
81 const CurrentThreadHolder::Ptr currentThreadHolder (getCurrentThreadHolder());
82 currentThreadHolder->value =
this;
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;
282 threadPriority = newPriority;
291 return setThreadPriority ({}, newPriority);
296 affinityMask = newAffinityMask;
302 return defaultEvent.
wait (timeOutMilliseconds);
321 std::function<void()> fn;
323 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (
LambdaThread)
329 anon->deleteOnThreadEnd =
true;
338 for (
int i = 20; --i >= 0;)
350 return juce_isRunningUnderDebugger();
359 AtomicTests() :
UnitTest (
"Atomics",
"Threads") {}
361 void runTest()
override
366 expect (numElementsInArray(a1) == 7);
368 expect (numElementsInArray(a2) == 3);
372 expect (
ByteOrder::swap ((uint64) 0x1122334455667788ULL) == 0x8877665544332211LL);
374 beginTest (
"Atomic int");
375 AtomicTester <int>::testInteger (*this);
376 beginTest (
"Atomic unsigned int");
377 AtomicTester <unsigned int>::testInteger (*this);
378 beginTest (
"Atomic int32");
379 AtomicTester <int32>::testInteger (*this);
380 beginTest (
"Atomic uint32");
381 AtomicTester <uint32>::testInteger (*this);
382 beginTest (
"Atomic long");
383 AtomicTester <long>::testInteger (*this);
384 beginTest (
"Atomic int*");
385 AtomicTester <int*>::testInteger (*this);
386 beginTest (
"Atomic float");
387 AtomicTester <float>::testFloat (*this);
388 #if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms
389 beginTest (
"Atomic int64");
390 AtomicTester <int64>::testInteger (*this);
391 beginTest (
"Atomic uint64");
392 AtomicTester <uint64>::testInteger (*this);
393 beginTest (
"Atomic double");
394 AtomicTester <double>::testFloat (*this);
396 beginTest (
"Atomic pointer increment/decrement");
397 Atomic<int*> a (a2);
int* b (a2);
401 beginTest (
"Atomic void*");
402 Atomic<void*> atomic;
405 atomic.set ((
void*) 10);
408 expect (atomic.value == c);
409 expect (atomic.get() == c);
413 template <
typename Type>
419 static void testInteger (UnitTest& test)
427 test.expect (a.value == c);
428 test.expect (a.get() == c);
432 test.expect (a.get() == c);
437 test.expect (a.get() == c);
439 test.expect (++a == ++c);
442 test.expect (--a == --c);
443 test.expect (a.get() == c);
451 static void testFloat (UnitTest& test)
460 test.expect (a.get() == (Type) 101);
461 test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
462 test.expect (a.get() == (Type) 101);
463 test.expect (a.compareAndSetBool ((Type) 200, a.get()));
464 test.expect (a.get() == (Type) 200);
466 test.expect (a.exchange ((Type) 300) == (Type) 200);
467 test.expect (a.get() == (Type) 300);
470 test.expect (b.get() == a.get());
475 static AtomicTests atomicUnitTests;
478 class ThreadLocalValueUnitTest :
public UnitTest,
482 ThreadLocalValueUnitTest()
483 : UnitTest (
"ThreadLocalValue",
"Threads"),
484 Thread (
"ThreadLocalValue Thread")
487 void runTest()
override
489 beginTest (
"values are thread local");
492 ThreadLocalValue<int> threadLocal;
494 sharedThreadLocal = &threadLocal;
496 sharedThreadLocal.get()->get() = 1;
499 signalThreadShouldExit();
500 waitForThreadToExit (-1);
502 mainThreadResult = sharedThreadLocal.get()->get();
504 expectEquals (mainThreadResult.get(), 1);
505 expectEquals (auxThreadResult.get(), 2);
508 beginTest (
"values are per-instance");
511 ThreadLocalValue<int> a, b;
516 expectEquals (a.get(), 1);
517 expectEquals (b.get(), 2);
522 Atomic<int> mainThreadResult, auxThreadResult;
523 Atomic<ThreadLocalValue<int>*> sharedThreadLocal;
527 sharedThreadLocal.get()->get() = 2;
528 auxThreadResult = sharedThreadLocal.get()->get();
532 ThreadLocalValueUnitTest threadLocalValueUnitTest;