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();
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;
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.