LMMS
Loading...
Searching...
No Matches
juce_Thread.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
30
32{
34 return;
35
36 /* If your thread class's destructor has been called without first stopping the thread, that
37 means that this partially destructed object is still performing some work - and that's
38 probably a Bad Thing!
39
40 To avoid this type of nastiness, always make sure you call stopThread() before or during
41 your subclass's destructor.
42 */
44
45 stopThread (-1);
46}
47
48//==============================================================================
49// Use a ref-counted object to hold this shared data, so that it can outlive its static
50// shared pointer when threads are still running during static shutdown.
60
61static char currentThreadHolderLock [sizeof (SpinLock)]; // (statically initialised to zeros).
62
64{
65 return static_cast<SpinLock*> (s);
66}
67
69{
70 static CurrentThreadHolder::Ptr currentThreadHolder;
72
73 if (currentThreadHolder == nullptr)
74 currentThreadHolder = new CurrentThreadHolder();
75
76 return currentThreadHolder;
77}
78
80{
81 const CurrentThreadHolder::Ptr currentThreadHolder (getCurrentThreadHolder());
82 currentThreadHolder->value = this;
83
84 if (threadName.isNotEmpty())
86
87 if (startSuspensionEvent.wait (10000))
88 {
90
91 if (affinityMask != 0)
93
94 try
95 {
96 run();
97 }
98 catch (...)
99 {
100 jassertfalse; // Your run() method mustn't throw any exceptions!
101 }
102 }
103
104 currentThreadHolder->value.releaseCurrentThreadStorage();
105
106 // Once closeThreadHandle is called this class may be deleted by a different
107 // thread, so we need to store deleteOnThreadEnd in a local variable.
108 auto shouldDeleteThis = deleteOnThreadEnd;
109 closeThreadHandle();
110
111 if (shouldDeleteThis)
112 delete this;
113}
114
115// used to wrap the incoming call from the platform-specific code
116void JUCE_API juce_threadEntryPoint (void* userData)
117{
118 static_cast<Thread*> (userData)->threadEntryPoint();
120
121//==============================================================================
123{
124 const ScopedLock sl (startStopLock);
125
126 shouldExit = 0;
127
128 if (threadHandle.get() == nullptr)
129 {
130 launchThread();
132 startSuspensionEvent.signal();
133 }
134}
135
136void Thread::startThread (int priority)
137{
138 const ScopedLock sl (startStopLock);
139
140 if (threadHandle.get() == nullptr)
141 {
142 #if JUCE_ANDROID
143 isAndroidRealtimeThread = (priority == realtimeAudioPriority);
144 #endif
145
147 startThread();
148 }
149 else
150 {
151 setPriority (priority);
152 }
153}
154
156{
157 return threadHandle.get() != nullptr;
158}
159
164
169
170//==============================================================================
172{
173 shouldExit = 1;
174 listeners.call ([] (Listener& l) { l.exitSignalSent(); });
175}
176
178{
179 return shouldExit.get() != 0;
180}
181
183{
184 if (auto* currentThread = getCurrentThread())
185 return currentThread->threadShouldExit();
186
187 return false;
188}
189
190bool Thread::waitForThreadToExit (const int timeOutMilliseconds) const
191{
192 // Doh! So how exactly do you expect this thread to wait for itself to stop??
194
195 auto timeoutEnd = Time::getMillisecondCounter() + (uint32) timeOutMilliseconds;
196
197 while (isThreadRunning())
198 {
199 if (timeOutMilliseconds >= 0 && Time::getMillisecondCounter() > timeoutEnd)
200 return false;
201
202 sleep (2);
203 }
204
205 return true;
206}
207
208bool Thread::stopThread (const int timeOutMilliseconds)
209{
210 // agh! You can't stop the thread that's calling this method! How on earth
211 // would that work??
213
214 const ScopedLock sl (startStopLock);
215
216 if (isThreadRunning())
217 {
219 notify();
220
221 if (timeOutMilliseconds != 0)
222 waitForThreadToExit (timeOutMilliseconds);
223
224 if (isThreadRunning())
225 {
226 // very bad karma if this point is reached, as there are bound to be
227 // locks and events left in silly states when a thread is killed by force..
229 Logger::writeToLog ("!! killing thread by force !!");
230
231 killThread();
232
233 threadHandle = nullptr;
234 threadId = {};
235 return false;
236 }
237 }
238
239 return true;
240}
241
243{
244 listeners.add (listener);
245}
246
248{
249 listeners.remove (listener);
250}
251
252//==============================================================================
253bool Thread::setPriority (int newPriority)
254{
255 newPriority = getAdjustedPriority (newPriority);
256
257 // NB: deadlock possible if you try to set the thread prio from the thread itself,
258 // so using setCurrentThreadPriority instead in that case.
260 return setCurrentThreadPriority (newPriority);
261
262 const ScopedLock sl (startStopLock);
263
264 #if JUCE_ANDROID
265 bool isRealtime = (newPriority == realtimeAudioPriority);
266
267 // you cannot switch from or to an Android realtime thread once the
268 // thread is already running!
269 jassert (isThreadRunning() && (isRealtime == isAndroidRealtimeThread));
270
271 isAndroidRealtimeThread = isRealtime;
272 #endif
273
274 if ((! isThreadRunning()) || setThreadPriority (threadHandle.get(), newPriority))
275 {
276 threadPriority = newPriority;
277 return true;
278 }
279
280 return false;
281}
282
283bool Thread::setCurrentThreadPriority (const int newPriority)
284{
285 return setThreadPriority ({}, getAdjustedPriority (newPriority));
286}
287
288void Thread::setAffinityMask (const uint32 newAffinityMask)
289{
290 affinityMask = newAffinityMask;
291}
292
293int Thread::getAdjustedPriority (int newPriority)
294{
295 return jlimit (0, 10, newPriority == realtimeAudioPriority ? 9 : newPriority);
296}
297
298//==============================================================================
299bool Thread::wait (const int timeOutMilliseconds) const
300{
301 return defaultEvent.wait (timeOutMilliseconds);
302}
303
304void Thread::notify() const
305{
306 defaultEvent.signal();
307}
308
309//==============================================================================
310struct LambdaThread : public Thread
311{
312 LambdaThread (std::function<void()> f) : Thread ("anonymous"), fn (f) {}
313
314 void run() override
315 {
316 fn();
317 fn = nullptr; // free any objects that the lambda might contain while the thread is still active
318 }
319
320 std::function<void()> fn;
321
323};
324
325void Thread::launch (std::function<void()> functionToRun)
326{
327 auto anon = new LambdaThread (functionToRun);
328 anon->deleteOnThreadEnd = true;
329 anon->startThread();
330}
331
332//==============================================================================
334{
335 if (! tryEnter())
336 {
337 for (int i = 20; --i >= 0;)
338 if (tryEnter())
339 return;
340
341 while (! tryEnter())
343 }
344}
345
346//==============================================================================
351
352
353//==============================================================================
354//==============================================================================
355#if JUCE_UNIT_TESTS
356
357class AtomicTests : public UnitTest
358{
359public:
360 AtomicTests()
361 : UnitTest ("Atomics", UnitTestCategories::threads)
362 {}
363
364 void runTest() override
365 {
366 beginTest ("Misc");
367
368 char a1[7];
369 expect (numElementsInArray(a1) == 7);
370 int a2[3];
371 expect (numElementsInArray(a2) == 3);
372
373 expect (ByteOrder::swap ((uint16) 0x1122) == 0x2211);
374 expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211);
375 expect (ByteOrder::swap ((uint64) 0x1122334455667788ULL) == (uint64) 0x8877665544332211LL);
376
377 beginTest ("Atomic int");
378 AtomicTester <int>::testInteger (*this);
379 beginTest ("Atomic unsigned int");
380 AtomicTester <unsigned int>::testInteger (*this);
381 beginTest ("Atomic int32");
382 AtomicTester <int32>::testInteger (*this);
383 beginTest ("Atomic uint32");
384 AtomicTester <uint32>::testInteger (*this);
385 beginTest ("Atomic long");
386 AtomicTester <long>::testInteger (*this);
387 beginTest ("Atomic int*");
388 AtomicTester <int*>::testInteger (*this);
389 beginTest ("Atomic float");
390 AtomicTester <float>::testFloat (*this);
391 #if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms
392 beginTest ("Atomic int64");
393 AtomicTester <int64>::testInteger (*this);
394 beginTest ("Atomic uint64");
395 AtomicTester <uint64>::testInteger (*this);
396 beginTest ("Atomic double");
397 AtomicTester <double>::testFloat (*this);
398 #endif
399 beginTest ("Atomic pointer increment/decrement");
400 Atomic<int*> a (a2); int* b (a2);
401 expect (++a == ++b);
402
403 {
404 beginTest ("Atomic void*");
405 Atomic<void*> atomic;
406 void* c;
407
408 atomic.set ((void*) 10);
409 c = (void*) 10;
410
411 expect (atomic.value == c);
412 expect (atomic.get() == c);
413 }
414 }
415
416 template <typename Type>
417 class AtomicTester
418 {
419 public:
420 AtomicTester() {}
421
422 static void testInteger (UnitTest& test)
423 {
424 Atomic<Type> a, b;
425 Type c;
426
427 a.set ((Type) 10);
428 c = (Type) 10;
429
430 test.expect (a.value == c);
431 test.expect (a.get() == c);
432
433 a += 15;
434 c += 15;
435 test.expect (a.get() == c);
436 a.memoryBarrier();
437
438 a -= 5;
439 c -= 5;
440 test.expect (a.get() == c);
441
442 test.expect (++a == ++c);
443 ++a;
444 ++c;
445 test.expect (--a == --c);
446 test.expect (a.get() == c);
447 a.memoryBarrier();
448
449 testFloat (test);
450 }
451
452
453
454 static void testFloat (UnitTest& test)
455 {
456 Atomic<Type> a, b;
457 a = (Type) 101;
458 a.memoryBarrier();
459
460 /* These are some simple test cases to check the atomics - let me know
461 if any of these assertions fail on your system!
462 */
463 test.expect (a.get() == (Type) 101);
464 test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
465 test.expect (a.get() == (Type) 101);
466 test.expect (a.compareAndSetBool ((Type) 200, a.get()));
467 test.expect (a.get() == (Type) 200);
468
469 test.expect (a.exchange ((Type) 300) == (Type) 200);
470 test.expect (a.get() == (Type) 300);
471
472 b = a;
473 test.expect (b.get() == a.get());
474 }
475 };
476};
477
478static AtomicTests atomicUnitTests;
479
480//==============================================================================
481class ThreadLocalValueUnitTest : public UnitTest,
482 private Thread
483{
484public:
485 ThreadLocalValueUnitTest()
486 : UnitTest ("ThreadLocalValue", UnitTestCategories::threads),
487 Thread ("ThreadLocalValue Thread")
488 {}
489
490 void runTest() override
491 {
492 beginTest ("values are thread local");
493
494 {
495 ThreadLocalValue<int> threadLocal;
496
497 sharedThreadLocal = &threadLocal;
498
499 sharedThreadLocal.get()->get() = 1;
500
501 startThread();
502 signalThreadShouldExit();
503 waitForThreadToExit (-1);
504
505 mainThreadResult = sharedThreadLocal.get()->get();
506
507 expectEquals (mainThreadResult.get(), 1);
508 expectEquals (auxThreadResult.get(), 2);
509 }
510
511 beginTest ("values are per-instance");
512
513 {
514 ThreadLocalValue<int> a, b;
515
516 a.get() = 1;
517 b.get() = 2;
518
519 expectEquals (a.get(), 1);
520 expectEquals (b.get(), 2);
521 }
522 }
523
524private:
525 Atomic<int> mainThreadResult, auxThreadResult;
526 Atomic<ThreadLocalValue<int>*> sharedThreadLocal;
527
528 void run() override
529 {
530 sharedThreadLocal.get()->get() = 2;
531 auxThreadResult = sharedThreadLocal.get()->get();
532 }
533};
534
535ThreadLocalValueUnitTest threadLocalValueUnitTest;
536
537#endif
538
539} // namespace juce
#define noexcept
Definition DistrhoDefines.h:72
uint8_t a
Definition Spc_Cpu.h:141
uint64_t uint64
Definition basics.h:92
uint16_t uint16
Definition basics.h:88
uint32_t uint32
Definition basics.h:90
static void run(LV2_Handle instance, uint32_t n_samples)
Definition bindings_test_plugin.c:112
static uint16 swap(uint16 value) noexcept
Definition ByteOrder.h:151
static void JUCE_CALLTYPE writeToLog(const String &message)
Definition juce_Logger.cpp:40
static bool JUCE_CALLTYPE isRunningUnderDebugger() noexcept
Definition juce_Thread.cpp:347
Definition juce_ReferenceCountedObject.h:247
Definition juce_SpinLock.h:42
void enter() const noexcept
Definition juce_Thread.cpp:333
bool tryEnter() const noexcept
Definition juce_SpinLock.h:59
GenericScopedLock< SpinLock > ScopedLockType
Definition juce_SpinLock.h:73
Definition juce_String.h:53
Definition juce_Thread.h:181
bool setPriority(int priority)
Definition juce_Thread.cpp:253
size_t threadStackSize
Definition juce_Thread.h:391
static void JUCE_CALLTYPE setCurrentThreadAffinityMask(uint32 affinityMask)
Definition juce_posix_SharedCode.h:1047
void setAffinityMask(uint32 affinityMask)
Definition juce_Thread.cpp:288
void * ThreadID
Definition juce_Thread.h:304
virtual ~Thread()
Definition juce_Thread.cpp:31
static Thread *JUCE_CALLTYPE getCurrentThread()
Definition juce_Thread.cpp:160
Atomic< void * > threadHandle
Definition juce_Thread.h:386
void startThread()
Definition juce_Thread.cpp:122
void launchThread()
Definition juce_posix_SharedCode.h:918
CriticalSection startStopLock
Definition juce_Thread.h:388
ListenerList< Listener, Array< Listener *, CriticalSection > > listeners
Definition juce_Thread.h:395
void threadEntryPoint()
Definition juce_Thread.cpp:79
bool wait(int timeOutMilliseconds) const
Definition juce_Thread.cpp:299
ThreadID getThreadId() const noexcept
Definition juce_Thread.cpp:165
bool waitForThreadToExit(int timeOutMilliseconds) const
Definition juce_Thread.cpp:190
static void JUCE_CALLTYPE yield()
Definition juce_posix_SharedCode.h:1033
@ realtimeAudioPriority
Definition juce_Thread.h:224
Thread(const String &threadName, size_t threadStackSize=0)
Definition juce_Thread.cpp:26
static bool currentThreadShouldExit()
Definition juce_Thread.cpp:182
bool threadShouldExit() const
Definition juce_Thread.cpp:177
bool deleteOnThreadEnd
Definition juce_Thread.h:393
void killThread()
Definition juce_posix_SharedCode.h:963
WaitableEvent defaultEvent
Definition juce_Thread.h:389
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
Definition juce_posix_SharedCode.h:1028
WaitableEvent startSuspensionEvent
Definition juce_Thread.h:389
static bool setThreadPriority(void *, int)
Definition juce_posix_SharedCode.h:993
bool stopThread(int timeOutMilliseconds)
Definition juce_Thread.cpp:208
void notify() const
Definition juce_Thread.cpp:304
static void JUCE_CALLTYPE setCurrentThreadName(const String &newThreadName)
Definition juce_posix_SharedCode.h:975
void addListener(Listener *)
Definition juce_Thread.cpp:242
static int getAdjustedPriority(int)
Definition juce_Thread.cpp:293
friend void JUCE_API juce_threadEntryPoint(void *)
Definition juce_Thread.cpp:116
Atomic< int32 > shouldExit
Definition juce_Thread.h:394
void signalThreadShouldExit()
Definition juce_Thread.cpp:171
Atomic< ThreadID > threadId
Definition juce_Thread.h:387
int threadPriority
Definition juce_Thread.h:390
static bool setCurrentThreadPriority(int priority)
Definition juce_Thread.cpp:283
bool isThreadRunning() const
Definition juce_Thread.cpp:155
uint32 affinityMask
Definition juce_Thread.h:392
const String threadName
Definition juce_Thread.h:385
void removeListener(Listener *)
Definition juce_Thread.cpp:247
static void launch(std::function< void()> functionToRun)
Definition juce_Thread.cpp:325
static void JUCE_CALLTYPE sleep(int milliseconds)
Definition juce_posix_SharedCode.h:44
Definition juce_ThreadLocalValue.h:48
static uint32 getMillisecondCounter() noexcept
Definition juce_Time.cpp:241
Definition juce_UnitTest.h:70
int * l
Definition inflate.c:1579
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned f
Definition inflate.c:1572
static const char * name
Definition pugl.h:1582
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE(className)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
#define JUCE_CALLTYPE
#define JUCE_API
Definition juce_StandardHeader.h:152
Definition juce_UnitTestCategories.h:27
Definition carla_juce.cpp:31
JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger() noexcept
Definition juce_linux_SystemStats.cpp:348
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
unsigned int uint32
Definition juce_MathsFunctions.h:45
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
static CurrentThreadHolder::Ptr getCurrentThreadHolder()
Definition juce_Thread.cpp:68
static char currentThreadHolderLock[sizeof(SpinLock)]
Definition juce_Thread.cpp:61
static SpinLock * castToSpinLockWithoutAliasingWarning(void *s)
Definition juce_Thread.cpp:63
Type
Definition Lv2Ports.h:60
static int test(SerdEnv *env, bool top_level, bool pretty_numbers)
Definition sratom_test.c:79
Definition juce_Thread.cpp:52
ThreadLocalValue< Thread * > value
Definition juce_Thread.cpp:56
CurrentThreadHolder() noexcept
Definition juce_Thread.cpp:53
ReferenceCountedObjectPtr< CurrentThreadHolder > Ptr
Definition juce_Thread.cpp:55
Definition juce_Thread.cpp:311
LambdaThread(std::function< void()> f)
Definition juce_Thread.cpp:312
void run() override
Definition juce_Thread.cpp:314
std::function< void()> fn
Definition juce_Thread.cpp:320
const char const char const char const char char * fn
Definition swell-functions.h:168
void DWORD stackSize
Definition swell-functions.h:807
return c
Definition crypt.c:175
b
Definition crypt.c:628
#define void
Definition unzip.h:396
#define const
Definition zconf.h:137