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();
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
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");
401 Atomic<int*> a (a2);
int* b (a2);
405 beginTest (
"Atomic void*");
406 Atomic<void*> atomic;
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)
431 test.expect (a.value == c);
432 test.expect (a.get() == c);
436 test.expect (a.get() == c);
441 test.expect (a.get() == c);
443 test.expect (++a == ++c);
446 test.expect (--a == --c);
447 test.expect (a.get() == c);
455 static void testFloat (UnitTest& test)
464 test.expect (a.get() == (Type) 101);
465 test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
466 test.expect (a.get() == (Type) 101);
467 test.expect (a.compareAndSetBool ((Type) 200, a.get()));
468 test.expect (a.get() == (Type) 200);
470 test.expect (a.exchange ((Type) 300) == (Type) 200);
471 test.expect (a.get() == (Type) 300);
474 test.expect (b.get() == a.get());
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");
496 ThreadLocalValue<int> threadLocal;
498 sharedThreadLocal = &threadLocal;
500 sharedThreadLocal.get()->get() = 1;
503 signalThreadShouldExit();
504 waitForThreadToExit (-1);
506 mainThreadResult = sharedThreadLocal.get()->get();
508 expectEquals (mainThreadResult.get(), 1);
509 expectEquals (auxThreadResult.get(), 2);
512 beginTest (
"values are per-instance");
515 ThreadLocalValue<int> a, b;
520 expectEquals (a.get(), 1);
521 expectEquals (b.get(), 2);
526 Atomic<int> mainThreadResult, auxThreadResult;
527 Atomic<ThreadLocalValue<int>*> sharedThreadLocal;
531 sharedThreadLocal.get()->get() = 2;
532 auxThreadResult = sharedThreadLocal.get()->get();
536 ThreadLocalValueUnitTest threadLocalValueUnitTest;
static JUCE_CONSTEXPR uint16 swap(uint16 value) noexcept
Swaps the upper and lower bytes of a 16-bit integer.
Automatically locks and unlocks a mutex object.
static void JUCE_CALLTYPE writeToLog(const String &message)
Writes a string to the current logger.
static bool JUCE_CALLTYPE isRunningUnderDebugger() noexcept
Returns true if this process is being hosted by a debugger.
A smart-pointer class which points to a reference-counted object.
ReferencedType * get() const noexcept
Returns the object that this pointer references.
A base class which provides methods for reference-counting.
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.
bool tryEnter() const noexcept
Attempts to acquire the lock, returning true if this was successful.
GenericScopedLock< SpinLock > ScopedLockType
Provides the type of scoped lock to use for locking a SpinLock.
bool isNotEmpty() const noexcept
Returns true if the string contains at least one character.
Provides cross-platform support for thread-local objects.
Used to receive callbacks for thread exit calls.
virtual void exitSignalSent()=0
Called if Thread::signalThreadShouldExit was called.
bool setPriority(int priority)
Changes the thread's priority.
void setAffinityMask(uint32 affinityMask)
Sets the affinity mask for the thread.
static void JUCE_CALLTYPE setCurrentThreadAffinityMask(uint32 affinityMask)
Changes the affinity mask for the caller thread.
void * ThreadID
A value type used for thread IDs.
static void JUCE_CALLTYPE sleep(int milliseconds)
Suspends the execution of the current thread until the specified timeout period has elapsed (note tha...
virtual ~Thread()
Destructor.
static Thread *JUCE_CALLTYPE getCurrentThread()
Finds the thread object that is currently running.
void startThread()
Starts the thread running.
bool wait(int timeOutMilliseconds) const
Suspends the execution of this thread until either the specified timeout period has elapsed,...
ThreadID getThreadId() const noexcept
Returns the ID of this thread.
bool waitForThreadToExit(int timeOutMilliseconds) const
Waits for the thread to stop.
static void JUCE_CALLTYPE setCurrentThreadName(const String &newThreadName)
Changes the name of the caller thread.
virtual void run()=0
Must be implemented to perform the thread's actual code.
Thread(const String &threadName, size_t threadStackSize=0)
Creates a thread.
static bool currentThreadShouldExit()
Checks whether the current thread has been told to stop running.
bool threadShouldExit() const
Checks whether the thread has been told to stop running.
static void JUCE_CALLTYPE yield()
Yields the current thread's CPU time-slot and allows a new thread to run.
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
Returns an id that identifies the caller thread.
bool stopThread(int timeOutMilliseconds)
Attempts to stop the thread running.
void notify() const
Wakes up the thread.
void addListener(Listener *)
Add a listener to this thread which will receive a callback when signalThreadShouldExit was called on...
void signalThreadShouldExit()
Sets a flag to tell the thread it should stop.
static bool setCurrentThreadPriority(int priority)
Changes the priority of the caller thread.
bool isThreadRunning() const
Returns true if the thread is currently active.
void removeListener(Listener *)
Removes a listener added with addListener.
static void launch(std::function< void()> functionToRun)
Invokes a lambda or function on its own thread.
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).
This is a base class for classes that perform a unit test.
bool wait(int timeOutMilliseconds=-1) const
Suspends the calling thread until the event has been signalled.
void signal() const
Wakes up any threads that are currently waiting on this object.
#define JUCE_API
This macro is added to all JUCE public class declarations.
Type get() const noexcept
Atomically reads and returns the current value.
void run() override
Must be implemented to perform the thread's actual code.