17 #ifndef DISTRHO_THREAD_HPP_INCLUDED
18 #define DISTRHO_THREAD_HPP_INCLUDED
24 #ifdef DISTRHO_OS_LINUX
25 # include <sys/prctl.h>
28 START_NAMESPACE_DISTRHO
39 Thread(
const char*
const threadName =
nullptr) noexcept
44 fHandle({
nullptr, 0}),
55 DISTRHO_SAFE_ASSERT(! isThreadRunning());
63 virtual void run() = 0;
71 bool isThreadRunning()
const noexcept
74 return (fHandle.p !=
nullptr);
76 return (fHandle != 0);
83 bool shouldThreadExit()
const noexcept
91 bool startThread(
const bool withRealtimePriority =
false) noexcept
94 DISTRHO_SAFE_ASSERT_RETURN(! isThreadRunning(),
true);
99 pthread_attr_init(&attr);
101 struct sched_param sched_param;
102 std::memset(&sched_param, 0,
sizeof(sched_param));
104 if (withRealtimePriority)
106 sched_param.sched_priority = 80;
108 #ifndef DISTRHO_OS_HAIKU
109 if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0 &&
110 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0 &&
111 # ifndef DISTRHO_OS_WINDOWS
112 (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0 ||
113 pthread_attr_setschedpolicy(&attr, SCHED_RR) == 0) &&
115 pthread_attr_setschedparam(&attr, &sched_param) == 0)
117 d_stdout(
"Thread setup with realtime priority successful");
122 d_stdout(
"Thread setup with realtime priority failed, going with normal priority instead");
123 pthread_attr_destroy(&attr);
124 pthread_attr_init(&attr);
132 bool ok = pthread_create(&handle, &attr, _entryPoint,
this) == 0;
133 pthread_attr_destroy(&attr);
135 if (withRealtimePriority && !ok)
137 d_stdout(
"Thread with realtime priority failed on creation, going with normal priority instead");
138 pthread_attr_init(&attr);
139 ok = pthread_create(&handle, &attr, _entryPoint,
this) == 0;
140 pthread_attr_destroy(&attr);
143 DISTRHO_SAFE_ASSERT_RETURN(ok,
false);
145 DISTRHO_SAFE_ASSERT_RETURN(handle.p !=
nullptr,
false);
147 DISTRHO_SAFE_ASSERT_RETURN(handle != 0,
false);
149 pthread_detach(handle);
164 bool stopThread(
const int timeOutMilliseconds) noexcept
168 if (isThreadRunning())
170 signalThreadShouldExit();
172 if (timeOutMilliseconds != 0)
175 int timeOutCheck = (timeOutMilliseconds == 1 || timeOutMilliseconds == -1) ? timeOutMilliseconds : timeOutMilliseconds/2;
177 for (; isThreadRunning();)
181 if (timeOutCheck < 0)
184 if (timeOutCheck > 0)
191 if (isThreadRunning())
194 d_stderr2(
"assertion failure: \"! isThreadRunning()\" in file %s, line %i", __FILE__, __LINE__);
201 pthread_detach(threadId);
212 void signalThreadShouldExit() noexcept
223 const String& getThreadName()
const noexcept
231 pthread_t getThreadId()
const noexcept
239 static void setCurrentThreadName(
const char*
const name) noexcept
241 DISTRHO_SAFE_ASSERT_RETURN(name !=
nullptr && name[0] !=
'\0',);
243 #ifdef DISTRHO_OS_LINUX
244 prctl(PR_SET_NAME, name, 0, 0, 0);
246 #if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012 && !defined(DISTRHO_OS_GNU_HURD)
247 pthread_setname_np(pthread_self(), name);
257 volatile pthread_t fHandle;
258 volatile bool fShouldExit;
263 void _init() noexcept
276 void _copyFrom(
const pthread_t& handle) noexcept
279 fHandle.p = handle.p;
280 fHandle.x = handle.x;
289 void _copyTo(
volatile pthread_t& handle)
const noexcept
292 handle.p = fHandle.p;
293 handle.x = fHandle.x;
302 void _runEntryPoint() noexcept
304 if (fName.isNotEmpty())
305 setCurrentThreadName(fName);
321 static void* _entryPoint(
void* userData) noexcept
323 static_cast<Thread*
>(userData)->_runEntryPoint();
327 DISTRHO_DECLARE_NON_COPYABLE(
Thread)
332 END_NAMESPACE_DISTRHO
334 #endif // DISTRHO_THREAD_HPP_INCLUDED