17 #ifndef DISTRHO_THREAD_HPP_INCLUDED
18 #define DISTRHO_THREAD_HPP_INCLUDED
24 #ifdef DISTRHO_OS_LINUX
25 # include <sys/prctl.h>
28 #ifdef DISTRHO_OS_WASM
29 # error Threads do not work under wasm!
43 Thread(
const char*
const threadName =
nullptr) noexcept
48 fHandle({
nullptr, 0}),
59 DISTRHO_SAFE_ASSERT(! isThreadRunning());
67 virtual void run() = 0;
75 bool isThreadRunning()
const noexcept
78 return (fHandle.p !=
nullptr);
80 return (fHandle != 0);
87 bool shouldThreadExit()
const noexcept
95 bool startThread(
const bool withRealtimePriority =
false) noexcept
98 DISTRHO_SAFE_ASSERT_RETURN(! isThreadRunning(),
true);
103 pthread_attr_init(&attr);
105 struct sched_param sched_param;
106 std::memset(&sched_param, 0,
sizeof(sched_param));
108 if (withRealtimePriority)
110 sched_param.sched_priority = 80;
112 #ifndef DISTRHO_OS_HAIKU
113 if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0 &&
114 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0 &&
115 # ifndef DISTRHO_OS_WINDOWS
116 (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0 ||
117 pthread_attr_setschedpolicy(&attr, SCHED_RR) == 0) &&
119 pthread_attr_setschedparam(&attr, &sched_param) == 0)
121 d_stdout(
"Thread setup with realtime priority successful");
126 d_stdout(
"Thread setup with realtime priority failed, going with normal priority instead");
127 pthread_attr_destroy(&attr);
128 pthread_attr_init(&attr);
136 bool ok = pthread_create(&handle, &attr, _entryPoint,
this) == 0;
137 pthread_attr_destroy(&attr);
139 if (withRealtimePriority && !ok)
141 d_stdout(
"Thread with realtime priority failed on creation, going with normal priority instead");
142 pthread_attr_init(&attr);
143 ok = pthread_create(&handle, &attr, _entryPoint,
this) == 0;
144 pthread_attr_destroy(&attr);
147 DISTRHO_SAFE_ASSERT_RETURN(ok,
false);
149 DISTRHO_SAFE_ASSERT_RETURN(handle.p !=
nullptr,
false);
151 DISTRHO_SAFE_ASSERT_RETURN(handle != 0,
false);
153 pthread_detach(handle);
168 bool stopThread(
const int timeOutMilliseconds) noexcept
172 if (isThreadRunning())
174 signalThreadShouldExit();
176 if (timeOutMilliseconds != 0)
179 int timeOutCheck = (timeOutMilliseconds == 1 || timeOutMilliseconds == -1) ? timeOutMilliseconds : timeOutMilliseconds/2;
181 for (; isThreadRunning();)
185 if (timeOutCheck < 0)
188 if (timeOutCheck > 0)
195 if (isThreadRunning())
198 d_stderr2(
"assertion failure: \"! isThreadRunning()\" in file %s, line %i", __FILE__, __LINE__);
205 pthread_detach(threadId);
216 void signalThreadShouldExit() noexcept
227 const String& getThreadName()
const noexcept
235 pthread_t getThreadId()
const noexcept
243 static void setCurrentThreadName(
const char*
const name) noexcept
245 DISTRHO_SAFE_ASSERT_RETURN(name !=
nullptr && name[0] !=
'\0',);
247 #ifdef DISTRHO_OS_LINUX
248 prctl(PR_SET_NAME, name, 0, 0, 0);
250 #if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012 && !defined(DISTRHO_OS_GNU_HURD)
251 pthread_setname_np(pthread_self(), name);
261 volatile pthread_t fHandle;
262 volatile bool fShouldExit;
267 void _init() noexcept
280 void _copyFrom(
const pthread_t& handle) noexcept
283 fHandle.p = handle.p;
284 fHandle.x = handle.x;
293 void _copyTo(
volatile pthread_t& handle)
const noexcept
296 handle.p = fHandle.p;
297 handle.x = fHandle.x;
306 void _runEntryPoint() noexcept
308 if (fName.isNotEmpty())
309 setCurrentThreadName(fName);
325 static void* _entryPoint(
void* userData) noexcept
327 static_cast<Thread*
>(userData)->_runEntryPoint();
331 DISTRHO_DECLARE_NON_COPYABLE(
Thread)
Definition: Mutex.hpp:269
Definition: Mutex.hpp:187
Definition: String.hpp:31
Definition: Thread.hpp:38
#define END_NAMESPACE_DISTRHO
Definition: DistrhoInfo.hpp:834
#define START_NAMESPACE_DISTRHO
Definition: DistrhoInfo.hpp:828
static void d_stdout(const char *const fmt,...) noexcept
Definition: DistrhoUtils.hpp:131
static void d_stderr2(const char *const fmt,...) noexcept
Definition: DistrhoUtils.hpp:161