27 : threadName (name), threadStackSize (stackSize)
33 if (deleteOnThreadEnd)
61static char currentThreadHolderLock [
sizeof (
SpinLock)];
63static SpinLock* castToSpinLockWithoutAliasingWarning (
void* s)
68static CurrentThreadHolder::Ptr getCurrentThreadHolder()
70 static CurrentThreadHolder::Ptr currentThreadHolder;
73 if (currentThreadHolder ==
nullptr)
74 currentThreadHolder =
new CurrentThreadHolder();
76 return currentThreadHolder;
79void 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)
116void 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);
370 expect (ByteOrder::swap ((uint16) 0x1122) == 0x2211);
371 expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211);
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
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());
475static AtomicTests atomicUnitTests;
478class 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();
532ThreadLocalValueUnitTest threadLocalValueUnitTest;
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 noexcept
Suspends the calling thread until the event has been signalled.
void signal() const noexcept
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.