27 : threadName (name), threadStackSize (stackSize)
33 if (deleteOnThreadEnd)
61 static char currentThreadHolderLock [
sizeof (
SpinLock)];
63 static SpinLock* castToSpinLockWithoutAliasingWarning (
void* s)
73 if (currentThreadHolder ==
nullptr)
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();
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");
401 beginTest (
"Atomic void*");
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)
451 static void testFloat (
UnitTest& test)
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");
494 sharedThreadLocal = &threadLocal;
496 sharedThreadLocal.
get()->get() = 1;
502 mainThreadResult = sharedThreadLocal.get()->get();
504 expectEquals (mainThreadResult.get(), 1);
505 expectEquals (auxThreadResult.get(), 2);
508 beginTest (
"values are per-instance");
516 expectEquals (a.
get(), 1);
517 expectEquals (b.
get(), 2);
527 sharedThreadLocal.
get()->get() = 2;
528 auxThreadResult = sharedThreadLocal.
get()->get();
532 ThreadLocalValueUnitTest threadLocalValueUnitTest;
A simple wrapper around std::atomic.
#define JUCE_API
This macro is added to all JUCE public class declarations.
bool stopThread(int timeOutMilliseconds)
Attempts to stop the thread running.
void addListener(Listener *)
Add a listener to this thread which will receive a callback when signalThreadShouldExit was called on...
void * ThreadID
A value type used for thread IDs.
static void launch(std::function< void()> functionToRun)
Invokes a lambda or function on its own thread.
void set(Type newValue) noexcept
Atomically sets the current value.
Thread(const String &threadName, size_t threadStackSize=0)
Creates a thread.
void signalThreadShouldExit()
Sets a flag to tell the thread it should stop.
static bool currentThreadShouldExit()
Checks whether the current thread has been told to stop running.
void run() override
Must be implemented to perform the thread's actual code.
virtual void run()=0
Must be implemented to perform the thread's actual code.
void notify() const
Wakes up the thread.
virtual ~Thread()
Destructor.
void setAffinityMask(uint32 affinityMask)
Sets the affinity mask for the thread.
This is a base class for classes that perform a unit test.
static void JUCE_CALLTYPE yield()
Yields the current thread's CPU time-slot and allows a new thread to run.
ThreadID getThreadId() const noexcept
Returns the ID of this thread.
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
Returns an id that identifies the caller thread.
std::atomic< Type > value
The std::atomic object that this class operates on.
A simple spin-lock class that can be used as a simple, low-overhead mutex for uncontended situations...
void enter() const noexcept
Acquires the lock.
Used to receive callbacks for thread exit calls.
static JUCE_CONSTEXPR uint16 swap(uint16 value) noexcept
Swaps the upper and lower bytes of a 16-bit integer.
bool threadShouldExit() const
Checks whether the thread has been told to stop running.
Provides cross-platform support for thread-local objects.
ReferencedType * get() const noexcept
Returns the object that this pointer references.
Type exchange(Type newValue) noexcept
Atomically sets the current value, returning the value that was replaced.
bool setPriority(int priority)
Changes the thread's priority.
void expect(bool testResult, const String &failureMessage=String())
Checks that the result of a test is true, and logs this result.
static void JUCE_CALLTYPE writeToLog(const String &message)
Writes a string to the current logger.
void memoryBarrier() noexcept
Implements a memory read/write barrier.
virtual void exitSignalSent()=0
Called if Thread::signalThreadShouldExit was called.
bool waitForThreadToExit(int timeOutMilliseconds) const
Waits for the thread to stop.
Type get() const noexcept
Atomically reads and returns the current value.
bool isThreadRunning() const
Returns true if the thread is currently active.
Type & get() const noexcept
Returns a reference to this thread's instance of the value.
A smart-pointer class which points to a reference-counted object.
bool compareAndSetBool(Type newValue, Type valueToCompare) noexcept
Atomically compares this value with a target value, and if it is equal, sets this to be equal to a ne...
static void JUCE_CALLTYPE setCurrentThreadAffinityMask(uint32 affinityMask)
Changes the affinity mask for the caller thread.
static void JUCE_CALLTYPE sleep(int milliseconds)
Suspends the execution of the current thread until the specified timeout period has elapsed (note tha...
A base class which provides methods for reference-counting.
static Thread *JUCE_CALLTYPE getCurrentThread()
Finds the thread object that is currently running.
Automatically locks and unlocks a mutex object.
static bool setCurrentThreadPriority(int priority)
Changes the priority of the caller thread.
static bool JUCE_CALLTYPE isRunningUnderDebugger() noexcept
Returns true if this process is being hosted by a debugger.
bool wait(int timeOutMilliseconds) const
Suspends the execution of this thread until either the specified timeout period has elapsed...
void removeListener(Listener *)
Removes a listener added with addListener.
void startThread()
Starts the thread running.
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).
static void JUCE_CALLTYPE setCurrentThreadName(const String &newThreadName)
Changes the name of the caller thread.