/[svn]/linuxsampler/trunk/src/common/Thread.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/common/Thread.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3764 - (hide annotations) (download)
Sun Apr 5 21:41:27 2020 UTC (4 years ago) by schoenebeck
File size: 21096 byte(s)
Thread class: Added new methods (POSIX implementation only yet):

* Added methods pushCancelable() and popCancelable() for allowing to
  prevent thread being terminated on critical sections.

* Added methods name(), nameOfCaller() and setNameOfCaller() to allow
  assigning threads human readable names for debugging purposes.

* configure: Always check for availability of pthread_testcancel()
  and use it if so (previously it was only used if explicitly enabled
  by configure script option).

* Raise a compiler warning if pthread_testcancel() is not available.

* Bumped version (2.1.1.svn52).

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 3764 * Copyright (C) 2005 - 2020 Christian Schoenebeck *
7 schoenebeck 53 * *
8     * This program is free software; you can redistribute it and/or modify *
9     * it under the terms of the GNU General Public License as published by *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13     * This program is distributed in the hope that it will be useful, *
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19     * along with this program; if not, write to the Free Software *
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24     #include "Thread.h"
25    
26 persson 2185 #if HAVE_CONFIG_H
27     # include <config.h>
28     #endif
29 schoenebeck 3764 #include "global_private.h"
30 persson 2185
31 schoenebeck 3764 #include <list>
32 schoenebeck 3290 #if DEBUG
33     # include <assert.h>
34     #endif
35    
36 schoenebeck 3764 #if !CONFIG_PTHREAD_TESTCANCEL
37     # warning No pthread_testcancel() available: this may lead to mutex dead locks when threads are stopped!
38     #endif
39    
40 schoenebeck 1221 // this is the minimum stack size a thread will be spawned with
41     // if this value is too small, the OS will allocate memory on demand and
42     // thus might lead to dropouts in realtime threads
43     // TODO: should be up for testing to get a reasonable good value
44     #define MIN_STACK_SIZE 524288
45    
46 schoenebeck 3764 #if !defined(WIN32)
47     static thread_local std::list<int> cancelStates;
48     #endif
49    
50 schoenebeck 1212 namespace LinuxSampler {
51    
52 schoenebeck 392 Thread::Thread(bool LockMemory, bool RealTime, int PriorityMax, int PriorityDelta) {
53     this->bLockedMemory = LockMemory;
54 schoenebeck 53 this->isRealTime = RealTime;
55     this->PriorityDelta = PriorityDelta;
56     this->PriorityMax = PriorityMax;
57 schoenebeck 3290 this->state = NOT_RUNNING;
58 senoner 1481 #if defined(WIN32)
59 schoenebeck 3290 # if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
60 senoner 1481 win32isRunning = false;
61 schoenebeck 3290 # endif
62 senoner 1481 #else
63 schoenebeck 53 __thread_destructor_key = 0;
64 schoenebeck 1221 pthread_attr_init(&__thread_attr);
65 senoner 1481 #endif
66 schoenebeck 53 }
67    
68     Thread::~Thread() {
69 schoenebeck 3290 // The thread must no longer be running at this point, otherwise it is an
70     // error (we should avoid an implied call of StopThread() in the destructor,
71     // because trying to do so might cause undefined behavior).
72     #if DEBUG
73     assert(!RunningCondition.GetUnsafe());
74 senoner 1481 #else
75 schoenebeck 3290 if (RunningCondition.GetUnsafe()) {
76     std::cerr << "WARNING: Thread destructed while still running!\n" << std::flush;
77     StopThread();
78     }
79     #endif
80     #if !defined(WIN32)
81 schoenebeck 1221 pthread_attr_destroy(&__thread_attr);
82 senoner 1481 #endif
83 schoenebeck 53 }
84    
85     /**
86 schoenebeck 3290 * Starts the thread synchronously. This method will block until the thread
87     * actually started it's execution before it will return. The abstract method
88 schoenebeck 57 * Main() is the entry point for the new thread. You have to implement the
89     * Main() method in your subclass.
90 schoenebeck 3290 *
91     * If this thread is already running when this method is called, then this
92     * method will detect this and return accordingly without further actions.
93     *
94     * @returns 0 on success, any other value if thread could not be launched
95 schoenebeck 53 */
96     int Thread::StartThread() {
97 schoenebeck 3290 int res = -1;
98 senoner 1481 #if defined (WIN32_SIGNALSTARTTHREAD_WORKAROUND)
99     // poll the win32isRunning variable and sleep 1msec inbetween
100     if(!win32isRunning) {
101 schoenebeck 3290 res = SignalStartThread();
102     if (res == 0) {
103     while (true) {
104     Sleep(1);
105     if (win32isRunning) break;
106     }
107 senoner 1481 }
108 schoenebeck 3290 } else res = 0;
109     #else
110     LockGuard g(RunningCondition);
111     // If the thread terminated on its own (i.e. returned from Main()) without
112     // any thread calling StopThread() yet, then the OS blocks termination of
113     // the thread waiting for a pthread_join() call. So we must detach the
114     // thread in this case, because otherwise it will cause a thread leak.
115     if (state == PENDING_JOIN) {
116     state = DETACHED;
117     #if !defined(WIN32)
118     pthread_detach(__thread_id);
119     #endif
120 senoner 1481 }
121 schoenebeck 1221 if (!RunningCondition.GetUnsafe()) {
122 schoenebeck 3290 res = SignalStartThread();
123     // if thread was triggered successfully, wait until thread actually
124     // started execution
125     if (res == 0)
126     RunningCondition.PreLockedWaitIf(false);
127     } else {
128     res = 0;
129 schoenebeck 57 }
130 senoner 1481 #endif
131 schoenebeck 3290 return res;
132 schoenebeck 57 }
133    
134     /**
135     * Starts the thread. This method will signal to start the thread and
136     * return immediately. Note that the thread might not yet run when this
137     * method returns! The abstract method Main() is the entry point for the
138     * new thread. You have to implement the Main() method in your subclass.
139     *
140 schoenebeck 3290 * @b IMPORTANT: Calling this method assumes that this thread is not yet
141     * running! Calling this method if the thread is already running causes
142     * undefined behavior!
143     *
144 schoenebeck 57 * @see StartThread()
145     */
146     int Thread::SignalStartThread() {
147 schoenebeck 3290 state = RUNNING;
148 senoner 1481 #if defined(WIN32)
149     LPVOID lpParameter;
150     hThread = CreateThread(
151     NULL, // no security attributes
152     MIN_STACK_SIZE,
153 schoenebeck 3290 win32threadLauncher,
154 senoner 1481 this,
155     0,
156     &lpThreadId);
157     if(hThread == NULL) {
158     std::cerr << "Thread creation failed: Error" << GetLastError() << std::endl << std::flush;
159     #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
160     win32isRunning = false;
161     #else
162     RunningCondition.Set(false);
163     #endif
164     return -1;
165     }
166     return 0;
167     #else
168 schoenebeck 1221 // prepare the thread properties
169     int res = pthread_attr_setinheritsched(&__thread_attr, PTHREAD_EXPLICIT_SCHED);
170     if (res) {
171     std::cerr << "Thread creation failed: Could not inherit thread properties."
172     << std::endl << std::flush;
173     RunningCondition.Set(false);
174     return res;
175     }
176     res = pthread_attr_setdetachstate(&__thread_attr, PTHREAD_CREATE_JOINABLE);
177     if (res) {
178     std::cerr << "Thread creation failed: Could not request a joinable thread."
179     << std::endl << std::flush;
180     RunningCondition.Set(false);
181     return res;
182     }
183     res = pthread_attr_setscope(&__thread_attr, PTHREAD_SCOPE_SYSTEM);
184     if (res) {
185     std::cerr << "Thread creation failed: Could not request system scope for thread scheduling."
186     << std::endl << std::flush;
187     RunningCondition.Set(false);
188     return res;
189     }
190     res = pthread_attr_setstacksize(&__thread_attr, MIN_STACK_SIZE);
191     if (res) {
192     std::cerr << "Thread creation failed: Could not set minimum stack size."
193     << std::endl << std::flush;
194     RunningCondition.Set(false);
195     return res;
196     }
197 nagata 1649
198 schoenebeck 53 // Create and run the thread
199 schoenebeck 3290 res = pthread_create(&this->__thread_id, &__thread_attr, pthreadLauncher, this);
200 schoenebeck 53 switch (res) {
201     case 0: // Success
202     break;
203     case EAGAIN:
204     std::cerr << "Thread creation failed: System doesn't allow to create another thread."
205     << std::endl << std::flush;
206 schoenebeck 1221 RunningCondition.Set(false);
207 schoenebeck 53 break;
208     case EPERM:
209     std::cerr << "Thread creation failed: You're lacking permisssions to set required scheduling policy and parameters."
210     << std::endl << std::flush;
211 schoenebeck 1221 RunningCondition.Set(false);
212 schoenebeck 53 break;
213     default:
214     std::cerr << "Thread creation failed: Unknown cause."
215     << std::endl << std::flush;
216 schoenebeck 1221 RunningCondition.Set(false);
217 schoenebeck 53 break;
218     }
219     return res;
220 senoner 1481 #endif
221 schoenebeck 53 }
222    
223     /**
224 schoenebeck 3290 * Stops the thread synchronously. This method will block until the thread
225     * actually stopped its execution before it will return from this method.
226     *
227     * If the thread is not running when calling this method, this will be detected
228     * and the call will be ignored. So it is safe to call this method both if the
229     * thread never started, as well as if the thread has already been stopped. And
230     * in fact you should explicitly call StopThread() before the Thread object is
231     * going to be destructured!
232     *
233     * @see SignalStopThread()
234 schoenebeck 53 */
235     int Thread::StopThread() {
236 senoner 1481 #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
237     SignalStopThread();
238     win32isRunning = false;
239     return 0;
240 schoenebeck 3290 #else
241     // LockGuard cannot be used here, because this is a bit more tricky here
242 schoenebeck 1221 RunningCondition.Lock();
243 schoenebeck 3290 #if !defined(WIN32)
244     // if thread was calling StopThread() on itself
245     if (pthread_equal(__thread_id, pthread_self())) {
246     RunningCondition.PreLockedSet(false);
247     state = DETACHED;
248     pthread_detach(__thread_id);
249     RunningCondition.Unlock();
250     pthread_exit(NULL);
251     }
252     #endif
253     // if we are here, then any other thread called StopThread() but not the thread itself
254 schoenebeck 1221 if (RunningCondition.GetUnsafe()) {
255 schoenebeck 53 SignalStopThread();
256 schoenebeck 1221 // wait until thread stopped execution
257 schoenebeck 3290 RunningCondition.PreLockedWaitAndUnlockIf(true);
258     #if !defined(WIN32)
259     pthread_join(__thread_id, NULL);
260     #endif
261     RunningCondition.Lock();
262     }
263     // If the thread terminated on its own (i.e. returned from Main()) without
264     // any thread calling StopThread() yet, then the OS blocks termination of
265     // the thread waiting for a pthread_join() call. So we must detach the
266     // thread in this case, because otherwise it will cause a thread leak.
267     if (state == PENDING_JOIN) {
268     state = DETACHED;
269     #if !defined(WIN32)
270 schoenebeck 351 pthread_detach(__thread_id);
271 schoenebeck 3290 #endif
272 schoenebeck 53 }
273 schoenebeck 1221 RunningCondition.Unlock();
274 schoenebeck 53 return 0;
275 schoenebeck 3290 #endif
276 schoenebeck 53 }
277    
278     /**
279 schoenebeck 3290 * Stops the thread asynchronously. This method will signal to stop the thread
280     * and return immediately. Note that due to this the thread might still run
281     * when this method returns!
282 schoenebeck 57 *
283 schoenebeck 3290 * @b IMPORTANT: You @ MUST still call StopThread() before destructing the
284     * Thread object, even if you called SignalStopThread() before and the thread
285     * is no longer running! Otherwise this may lead to a thread leak!
286     *
287 schoenebeck 57 * @see StopThread()
288 schoenebeck 53 */
289     int Thread::SignalStopThread() {
290 schoenebeck 1221 //FIXME: segfaults when thread is not yet running
291 senoner 1481 #if defined(WIN32)
292     BOOL res;
293     res = TerminateThread(hThread, 0); // we set ExitCode to 0
294     //res = WaitForSingleObject( hThread, INFINITE);
295     //myprint(("Thread::SignalStopThread: WaitForSingleObject( hThread, INFINITE) res=%d\n",res));
296     #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
297     win32isRunning = false;
298     #else
299     RunningCondition.Set(false);
300     #endif
301 nagata 1649 #else
302 schoenebeck 53 pthread_cancel(__thread_id);
303 senoner 1481 #endif
304 schoenebeck 53 return 0;
305     }
306    
307     /**
308 schoenebeck 3290 * Returns @c true in case the thread is currently running. This method does not
309     * block and returns immediately.
310     *
311     * Note that no synchronization is performed when calling this method. So the
312     * returned result is a very volatile information which must be processed with
313     * precautions, that is it may not be used for code that might cause a race
314     * condition.
315 schoenebeck 1212 */
316     bool Thread::IsRunning() {
317 senoner 1481 #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
318     return win32isRunning;
319     #else
320 schoenebeck 1221 return RunningCondition.GetUnsafe();
321 senoner 1481 #endif
322 schoenebeck 1212 }
323    
324     /**
325 schoenebeck 53 * Sets the process SCHED_FIFO policy, if max=1 then set at max priority,
326     * else use min priority. delta is added to the priority so that we can
327     * for example set 3 SCHED_FIFO tasks to different priorities by specifying
328     * delta 0 , -1 , -2 ( 0 = highest priority because -1 is subtracted to the
329     * current priority).
330     */
331     int Thread::SetSchedulingPriority() {
332 senoner 1481 #if defined(WIN32)
333     DWORD dwPriorityClass;
334     int nPriority;
335    
336     if(isRealTime) {
337     dwPriorityClass = REALTIME_PRIORITY_CLASS;
338     if (this->PriorityMax == 1) {
339     if(this->PriorityDelta == 0) nPriority = THREAD_PRIORITY_TIME_CRITICAL;
340     else nPriority = 7 + this->PriorityDelta;
341     }
342     else nPriority = THREAD_PRIORITY_NORMAL + this->PriorityDelta;
343     }
344     else {
345     dwPriorityClass = NORMAL_PRIORITY_CLASS;
346     nPriority = THREAD_PRIORITY_NORMAL + this->PriorityDelta;
347     }
348    
349     BOOL res;
350     // FIXME: priority class (realtime) does not work yet, gives error. check why.
351     #if 0
352     res = SetPriorityClass( hThread, dwPriorityClass );
353     if(res == false) {
354     std::cerr << "Thread: WARNING, setPriorityClass " << dwPriorityClass << "failed. Error " << GetLastError() << "\n";
355     return -1;
356     }
357    
358     res = SetThreadPriority( hThread, nPriority );
359     if(res == false) {
360     std::cerr << "Thread: WARNING, setThreadPriority " << nPriority << "failed. Error " << GetLastError() << "\n";
361     return -1;
362     }
363     #endif
364     return 0;
365     #else
366 schoenebeck 361 #if !defined(__APPLE__)
367 schoenebeck 1221 int policy;
368 persson 1222 const char* policyDescription = NULL;
369 schoenebeck 1221 if (isRealTime) { // becomes a RT thread
370     policy = SCHED_FIFO;
371     policyDescription = "realtime";
372     } else { // 'normal', non-RT thread
373     policy = SCHED_OTHER;
374     policyDescription = "normal (non-RT)";
375     }
376     // set selected scheduling policy and priority
377 schoenebeck 53 struct sched_param schp;
378     memset(&schp, 0, sizeof(schp));
379 persson 1222 if (isRealTime) { // it is not possible to change priority for the SCHED_OTHER policy
380     if (this->PriorityMax == 1) {
381     schp.sched_priority = sched_get_priority_max(policy) + this->PriorityDelta;
382     }
383     if (this->PriorityMax == -1) {
384     schp.sched_priority = sched_get_priority_min(policy) + this->PriorityDelta;
385     }
386 schoenebeck 53 }
387 schoenebeck 1221 if (pthread_setschedparam(__thread_id, policy, &schp) != 0) {
388     std::cerr << "Thread: WARNING, can't assign "
389     << policyDescription
390     << " scheduling to thread!"
391     << std::endl << std::flush;
392 schoenebeck 53 return -1;
393     }
394 schoenebeck 361 #endif
395 schoenebeck 53 return 0;
396 senoner 1481 #endif
397 schoenebeck 53 }
398    
399     /**
400 schoenebeck 392 * Locks the memory so it will not be swapped out by the operating system.
401     */
402     int Thread::LockMemory() {
403 senoner 1481 #if defined(WIN32)
404     return 0;
405     #else
406 letz 399 #if !defined(__APPLE__)
407 schoenebeck 392 if (!bLockedMemory) return 0;
408     if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0) {
409 schoenebeck 1221 std::cerr << "Thread: WARNING, can't mlockall() memory!\n"
410     << std::flush;
411 schoenebeck 392 return -1;
412     }
413 letz 399 #endif
414 schoenebeck 392 return 0;
415 senoner 1481 #endif
416 schoenebeck 392 }
417    
418     /**
419 schoenebeck 53 * Registers thread destructor callback function which will be executed when
420     * the thread stops it's execution and sets the 'Running' flag to true. This
421 schoenebeck 3290 * method will be called by the pthreadLauncher callback function, DO NOT
422 schoenebeck 53 * CALL THIS METHOD YOURSELF!
423     */
424     void Thread::EnableDestructor() {
425 senoner 1481 #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
426     win32isRunning = true;
427     return;
428     #endif
429 schoenebeck 3290 LockGuard g(RunningCondition);
430     #if !defined(WIN32)
431     pthread_key_create(&__thread_destructor_key, pthreadDestructor);
432 schoenebeck 53 pthread_setspecific(__thread_destructor_key, this);
433 schoenebeck 3290 #endif
434     RunningCondition.PreLockedSet(true);
435 schoenebeck 53 }
436    
437     /**
438 schoenebeck 3290 * May be overridden by deriving classes to add additional custom cleanup
439     * code if necessary for the event when thread terminates. Currently this
440     * default implementation does nothing.
441 schoenebeck 53 */
442 schoenebeck 3290 int Thread::onThreadEnd() {
443 persson 497 return 0;
444 schoenebeck 53 }
445    
446 persson 2185 void Thread::TestCancel() {
447 schoenebeck 3290 #if !defined(WIN32)
448 persson 2185 pthread_testcancel();
449     #endif
450     }
451    
452 senoner 1481 #if defined(WIN32)
453 persson 3020 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
454     // make sure stack is 16-byte aligned for SSE instructions
455     __attribute__((force_align_arg_pointer))
456     #endif
457 schoenebeck 3290 DWORD WINAPI Thread::win32threadLauncher(LPVOID lpParameter) {
458 senoner 1481 Thread* t;
459     t = (Thread*) lpParameter;
460     t->SetSchedulingPriority();
461     t->LockMemory();
462     t->EnableDestructor();
463     t->Main();
464     return 0;
465     }
466     #else
467 schoenebeck 53 /// Callback function for the POSIX thread API
468 schoenebeck 3290 void* Thread::pthreadLauncher(void* thread) {
469 nagata 1649 #if !CONFIG_PTHREAD_TESTCANCEL
470 schoenebeck 3290 // let the thread be killable under any circumstances
471     if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
472     std::cerr << "Thread: WARNING, PTHREAD_CANCEL_ASYNCHRONOUS not supported!\n" << std::flush;
473     }
474 nagata 1649 #endif
475 schoenebeck 3290 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
476 schoenebeck 53 Thread* t;
477     t = (Thread*) thread;
478 schoenebeck 57 t->SetSchedulingPriority();
479 schoenebeck 392 t->LockMemory();
480 schoenebeck 53 t->EnableDestructor();
481     t->Main();
482 persson 497 return NULL;
483 schoenebeck 53 }
484 senoner 1481 #endif
485 schoenebeck 53
486 schoenebeck 3290 #if !defined(WIN32)
487 schoenebeck 53 /// Callback function for the POSIX thread API
488 schoenebeck 3290 void Thread::pthreadDestructor(void* thread) {
489 schoenebeck 53 Thread* t;
490     t = (Thread*) thread;
491 schoenebeck 3290 LockGuard g(t->RunningCondition);
492     t->onThreadEnd();
493     pthread_key_delete(t->__thread_destructor_key);
494     // inform that thread termination blocks waiting for pthread_join()
495     // (not detaching the thread here already, because otherwise this might lead
496     // to a data race of the vpointer with the Thread object destructor)
497     t->state = PENDING_JOIN;
498     t->RunningCondition.PreLockedSet(false);
499 schoenebeck 53 }
500 senoner 1481 #endif
501 schoenebeck 1212
502 schoenebeck 3764 /**
503     * Allow or prohibit whether the calling thread may be cancelled, remember its
504     * previous setting on a stack.
505     *
506     * @discussion The POSIX standard defines certaing system calls as implied
507     * thread cancellation points. For instance when a thread calls @c usleep(), the
508     * thread would immediately terminate if the thread was requested to be stopped.
509     * The problem with this is that a thread typically has critical sections where
510     * it may not simply terminate unexpectedly, e.g. if a thread is currently
511     * holding a mutex lock and then would call @c usleep() this may end up in a
512     * dead lock, since the lock would then never be unlocked again. For that reason
513     * a thread should first disable itself being cancelable before entering a
514     * critical section by calling @c pushCancelable(false) and it should
515     * re-enable thread cancelation by calling @c popCancelable() after having left
516     * the critical section(s). Refer to the following link for a list of functions
517     * being defined as implied cancelation points:
518     * http://man7.org/linux/man-pages/man7/pthreads.7.html
519     *
520     * @b NOTE: This method is currently not implemented for Windows yet!
521     *
522     * @param cancel - @c true: thread may be cancelled, @c false: thread may not
523     * be cancelled until re-enabled with either pushCancelable() or
524     * popCancelable()
525     * @see popCancelable() as counter part
526     */
527     void Thread::pushCancelable(bool cancel) {
528     #if defined(WIN32)
529     //TODO: implementation for Windows
530     #else
531     int old;
532     pthread_setcancelstate(cancel ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, &old);
533     cancelStates.push_back(old);
534     #endif
535     }
536    
537     /**
538     * Restore previous cancellation setting of calling thread by restoring it from
539     * stack.
540     *
541     * @b NOTE: This method is currently not implemented for Windows yet!
542     *
543     * @see pushCancelable() for details
544     */
545     void Thread::popCancelable() {
546     #if defined(WIN32)
547     //TODO: implementation for Windows
548     #else
549     int cancel = cancelStates.back();
550     cancelStates.pop_back();
551     pthread_setcancelstate(cancel ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, NULL);
552     #endif
553     }
554    
555     /**
556     * Return this thread's name (intended just for debugging purposes).
557     *
558     * @b NOTE: This method is currently not implemented for Windows yet!
559     */
560     std::string Thread::name() {
561     #if defined(WIN32)
562     //TODO: implementation for Windows
563     return "not implemented";
564     #else
565     char buf[16] = {};
566     pthread_getname_np(__thread_id, buf, 16);
567     std::string s = buf;
568     if (s.empty())
569     s = "tid=" + ToString(__thread_id);
570     return s;
571     #endif
572     }
573    
574     /**
575     * Return calling thread's name (intended just for debugging purposes).
576     *
577     * @b NOTE: This method is currently not implemented for Windows yet!
578     */
579     std::string Thread::nameOfCaller() {
580     #if defined(WIN32)
581     //TODO: implementation for Windows
582     return "not implemented";
583     #else
584     char buf[16] = {};
585     pthread_getname_np(pthread_self(), buf, 16);
586     std::string s = buf;
587     if (s.empty())
588     s = "tid=" + ToString(pthread_self());
589     return s;
590     #endif
591     }
592    
593     /**
594     * Give calling thread a name (intended just for debugging purposes).
595     *
596     * @b NOTE: POSIX defines a limit of max. 16 characters for @a name.
597     *
598     * @b NOTE: This method is currently not implemented for Windows yet!
599     *
600     * @param name - arbitrary, i.e. human readable name for calling thread
601     */
602     void Thread::setNameOfCaller(std::string name) {
603     #if defined(WIN32)
604     //TODO: implementation for Windows
605     #elif __APPLE__
606     pthread_setname_np(name.c_str());
607     #else // Linux, NetBSD, FreeBSD, ...
608     pthread_setname_np(pthread_self(), name.c_str());
609     #endif
610     }
611    
612 schoenebeck 1212 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC