globally remove all trailing whitespace from .cpp and .hpp files missed by previous...
[ardour.git] / libs / backends / wavesaudio / wavesapi / Threads / WCThreadSafe.cpp
1 #include "Threads/WCThreadSafe.h"
2 #include <glib.h>
3
4 #if XPLATFORMTHREADS_WINDOWS
5     #define _WIN32_WINNT 0x0500   // need at least Windows2000 (for TryEnterCriticalSection() and SignalObjectAndWait()
6     #include "IncludeWindows.h"
7     #include <process.h>
8 #endif // XPLATFORMTHREADS_WINDOWS
9
10
11 #if defined(__APPLE__)
12     #include <CoreServices/CoreServices.h>
13     #include <stdio.h>
14 #endif // __APPLE__
15
16 #if XPLATFORMTHREADS_POSIX
17     #include </usr/include/unistd.h>   // avoid the framework version and use the /usr/include version
18     #include <pthread.h>
19     #include <sched.h>
20     #include <sys/time.h>
21     #include <errno.h>
22     #include <signal.h>
23 // We do this externs because <stdio.h> comes from MSL
24 extern "C" FILE *popen(const char *command, const char *type);
25 extern "C" int pclose(FILE *stream);
26 static int (*BSDfread)( void *, size_t, size_t, FILE * ) = 0;
27
28 #include <string.h>
29
30 #endif //XPLATFORMTHREADS_POSIX
31
32 namespace wvNS {
33 static const unsigned int knMicrosecondsPerSecond = 1000*1000;
34 static const unsigned int knNanosecondsPerMicrosecond = 1000;
35 static const unsigned int knNanosecondsPerSecond = knMicrosecondsPerSecond*knNanosecondsPerMicrosecond;
36
37 namespace wvThread
38 {
39
40     //--------------------------------------------------------------------------------
41     static inline bool EnsureThreadingInitialized()
42     {
43         bool bRetval = true;
44
45         return bRetval;
46     }
47     //--------------------------------------------------------------------------------
48
49
50
51
52     //--------------------------------------------------------------------------------
53     static uint32_t CalculateTicksPerMicrosecond();
54     static uint32_t CalculateTicksPerMicrosecond()
55     {
56         uint32_t nTicksPerMicrosecond=0;
57 #if defined(_WIN32)
58         LARGE_INTEGER TSC;
59         ::QueryPerformanceFrequency(&TSC);
60         nTicksPerMicrosecond = uint32_t (TSC.QuadPart / knMicrosecondsPerSecond);
61 #elif defined(__linux__) && defined(__i386__)
62         static const timediff sktd_TSC_MeasurementPeriod = 40*1000; // delay for CalculateTicksPerMicrosecond() to measure the TSC frequency
63         uint64_t Tstart, Tend;
64         timeval tvtmp, tvstart, tvend;
65
66         //--------------------- begin measurement code
67         // poll to align to a tick of gettimeofday
68         ::gettimeofday(&tvtmp,0);
69         do {
70             ::gettimeofday(&tvstart,0);
71             __asm__ __volatile__ (".byte 0x0f, 0x31" : "=A" (Tstart));  // RDTSC
72         } while (tvtmp.tv_usec!=tvstart.tv_usec);
73         // delay some
74         ::usleep(sktd_TSC_MeasurementPeriod);
75         //
76         ::gettimeofday(&tvtmp,0);
77         do {
78             ::gettimeofday(&tvend,0);
79             __asm__ __volatile__ (".byte 0x0f, 0x31" : "=A" (Tend));    // RDTSC
80         } while (tvtmp.tv_usec!=tvend.tv_usec);
81         //--------------------- end measurement code
82
83         suseconds_t elapsed_usec = (tvend.tv_sec-tvstart.tv_sec)*knMicrosecondsPerSecond + (tvend.tv_usec-tvstart.tv_usec);
84         uint64_t elapsed_ticks = Tend-Tstart;
85         nTicksPerMicrosecond = uint32_t (elapsed_ticks/elapsed_usec);
86 #endif
87         return nTicksPerMicrosecond;
88     }
89
90 #if defined(__APPLE__) //&& !defined(__MACH__)
91
92
93     bool FindNetInterfaceByIPAddress(const char *sIP, char *sInterface) // sIP and sInterface are both char[16]
94     {
95         FILE *fProcess , *pSubcall;
96         char sLine[256]="", *pToken, sCommand[150];
97         bool res = false;
98         int iret;
99
100         fProcess = popen("ifconfig -l inet", "r");
101         if (fProcess)
102         {
103             memset(sInterface, '\0', 16);
104             iret = BSDfread(sLine, sizeof(char), sizeof(sLine), fProcess);
105             pToken = strtok(sLine, " ");
106             while (pToken)
107             {
108                 sprintf(sCommand, "ifconfig %s | grep \"inet %s \"", pToken, sIP);
109
110                 pSubcall = popen(sCommand, "r");
111                 if (pSubcall)
112                 {
113                     char sSubline[100]="";
114                     if (BSDfread(sSubline, sizeof(char), sizeof(sSubline), pSubcall))
115                     {
116                         // found
117                         strcpy(sInterface, pToken);
118                         res = true;
119                         pclose(pSubcall);
120                         break;
121                     }
122                 }
123                 pclose(pSubcall);
124                 pToken = strtok(NULL, " ");
125             }
126
127         }
128         pclose(fProcess);
129
130         return res;
131     }
132 #endif // MACOS
133
134     timestamp now(void)
135     {
136         EnsureThreadingInitialized();
137         static const uint32_t nTicksPerMicrosecond = CalculateTicksPerMicrosecond();
138 #if defined(_WIN32)
139         if (nTicksPerMicrosecond)
140         {
141             LARGE_INTEGER TSC;
142             ::QueryPerformanceCounter(&TSC);
143             return timestamp(uint32_t(TSC.QuadPart/nTicksPerMicrosecond));
144         }
145         else return timestamp(0);
146 #elif defined(__APPLE__)
147         if (nTicksPerMicrosecond) {} // prevent 'unused' warnings
148         UnsignedWide usecs;
149         ::Microseconds(&usecs);
150         return timestamp(usecs.lo);
151 #elif defined(__linux__) && defined(__i386__) && defined(__gnu_linux__)
152         uint64_t TSC;
153         __asm__ __volatile__ (".byte 0x0f, 0x31" : "=A" (TSC));  // RDTSC
154         return timestamp(TSC/nTicksPerMicrosecond);
155 #elif defined(__linux__) && defined(__PPC__) && defined(__gnu_linux__)
156     #warning need to implement maybe
157 #else
158     #error Dont know how to get microseconds timer !
159 #endif // defined(_WIN32)
160     }
161
162
163     void sleep_milliseconds(unsigned int nMillisecs)
164     {
165         EnsureThreadingInitialized();
166 #if XPLATFORMTHREADS_WINDOWS
167         ::Sleep(nMillisecs);
168 #elif XPLATFORMTHREADS_POSIX
169         ::usleep(nMillisecs*1000);
170 #else
171     #error Not implemented for your OS
172 #endif
173     }
174
175
176 #if XPLATFORMTHREADS_WINDOWS
177     inline DWORD win32_milliseconds(timediff td) { return (td+499)/1000; }
178 #endif
179
180     void sleep(timediff _td)
181     {
182         if (_td>0)
183         {
184             EnsureThreadingInitialized();
185 #if XPLATFORMTHREADS_WINDOWS
186             ::Sleep(win32_milliseconds(_td));    // This is the best we can do in windows
187 #elif XPLATFORMTHREADS_POSIX
188             ::usleep(_td);
189 #else
190     #error Not implemented for your OS
191 #endif
192         }
193     }
194
195
196 #if XPLATFORMTHREADS_WINDOWS
197     void yield()   {  ::Sleep(0);   }
198 #elif XPLATFORMTHREADS_POSIX
199     void yield()   {  ::sched_yield();  }
200 #endif
201
202
203
204
205     class  ThreadMutexInited::OSDependentMutex : public noncopyableobject
206     {
207 #if defined (XPLATFORMTHREADS_WINDOWS)
208     protected:
209         CRITICAL_SECTION m_critsec;
210     public:
211
212         inline OSDependentMutex()  { EnsureThreadingInitialized(); ::InitializeCriticalSection(&m_critsec); }
213         inline ~OSDependentMutex() { EnsureThreadingInitialized(); ::DeleteCriticalSection    (&m_critsec); }
214         inline void obtain()       { EnsureThreadingInitialized(); ::EnterCriticalSection     (&m_critsec); }
215         inline void release()      { EnsureThreadingInitialized(); ::LeaveCriticalSection     (&m_critsec); }
216         inline bool tryobtain()    { EnsureThreadingInitialized(); return TryEnterCriticalSection(&m_critsec)!=FALSE; }
217
218 #elif defined (XPLATFORMTHREADS_POSIX)
219     protected:
220         pthread_mutex_t  m_ptmutex;
221     public:
222         inline OSDependentMutex()
223         {
224             EnsureThreadingInitialized();
225             pthread_mutexattr_t attr;
226             pthread_mutexattr_init(&attr);
227             pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
228             ::pthread_mutex_init (&m_ptmutex, &attr);
229         }
230         inline ~OSDependentMutex() { EnsureThreadingInitialized(); ::pthread_mutex_destroy(&m_ptmutex); }
231         inline void obtain()       { EnsureThreadingInitialized(); ::pthread_mutex_lock       (&m_ptmutex); }
232         inline void release()      { EnsureThreadingInitialized(); ::pthread_mutex_unlock     (&m_ptmutex); }
233         inline bool tryobtain()    { EnsureThreadingInitialized(); return ::pthread_mutex_trylock(&m_ptmutex)!=EBUSY; }
234
235 #endif
236     };
237
238     ThreadMutexInited::ThreadMutexInited() :
239                         m_osdmutex(0) {}
240
241     void ThreadMutexInited::init()
242     {
243         if (! is_init())
244         {
245             m_osdmutex = new OSDependentMutex;
246         }
247     }
248
249     void ThreadMutexInited::uninit()
250     {
251         if (is_init())
252         {
253             delete m_osdmutex;
254             m_osdmutex = 0;
255         }
256     }
257
258     ThreadMutexInited::~ThreadMutexInited()
259     {
260         uninit();
261     }
262
263     void ThreadMutexInited::obtain()
264     {
265         if (is_init())
266         {
267             m_osdmutex->obtain();
268         }
269     }
270
271     void ThreadMutexInited::release()
272     {
273         if (is_init())
274         {
275             m_osdmutex->release();
276         }
277     }
278
279     bool ThreadMutexInited::tryobtain()
280     {
281         bool retVal = true;
282         if (is_init())
283         {
284             retVal = m_osdmutex->tryobtain();
285         }
286         return retVal;
287     }
288
289     class ThreadConditionSignal::OSDependentObject : public noncopyableobject
290     {
291 #if defined (XPLATFORMTHREADS_POSIX)
292
293     protected:
294         pthread_cond_t  m_ptcond;
295         pthread_mutex_t m_ptmutex;
296     public:
297         inline OSDependentObject()
298         {
299             EnsureThreadingInitialized();
300             ::pthread_mutex_init(&m_ptmutex,0);
301             ::pthread_cond_init(&m_ptcond, 0);
302         }
303         inline ~OSDependentObject()     { ::pthread_cond_destroy(&m_ptcond), ::pthread_mutex_destroy(&m_ptmutex); }
304         inline void signal_unicast()    { ::pthread_cond_signal(&m_ptcond);    }
305         inline void signal_broadcast()  { ::pthread_cond_broadcast(&m_ptcond); }
306         inline void await_signal()      { ::pthread_cond_wait(&m_ptcond, &m_ptmutex); }
307         inline bool await_signal(timediff td)
308         {
309             timespec tspecDeadline;
310             timeval  tvNow;
311             ::gettimeofday(&tvNow,0);
312             tspecDeadline.tv_nsec = (tvNow.tv_usec + td%knMicrosecondsPerSecond)*knNanosecondsPerMicrosecond;
313             tspecDeadline.tv_sec  = tvNow.tv_sec  + td/knMicrosecondsPerSecond;
314             if (!(tspecDeadline.tv_nsec < suseconds_t(knNanosecondsPerSecond)))
315                 ++tspecDeadline.tv_sec, tspecDeadline.tv_nsec-=knNanosecondsPerSecond;
316             return ::pthread_cond_timedwait(&m_ptcond, &m_ptmutex, &tspecDeadline) != ETIMEDOUT;
317         }
318
319         void obtain_mutex()    { ::pthread_mutex_lock(&m_ptmutex); }
320         bool tryobtain_mutex() { return ::pthread_mutex_trylock(&m_ptmutex)!=EBUSY; }
321         void release_mutex()   { ::pthread_mutex_unlock(&m_ptmutex); }
322
323
324 #elif XPLATFORMTHREADS_WINDOWS
325     protected:
326         unsigned int     m_nWaiterCount;
327         CRITICAL_SECTION m_csectWaiterCount;
328
329         HANDLE m_hndSemaphoreSignaller;        // We keep this semaphore always at 0 count (non-signalled). We use it to release a controlled number of threads.
330         HANDLE m_hndEventAllWaitersReleased;   // auto-reset
331         HANDLE m_hndMutex;                     // the mutex associated with the condition
332         bool   m_bBroadcastSignalled;          // means that the last waiter must signal m_hndEventAllWaitersReleased when done waiting
333
334     protected:
335         // - - - - - - - - - - - - - - - - - - - - - - - -
336         bool await_signal_win32(DWORD dwTimeout)
337         {
338             ::EnterCriticalSection(&m_csectWaiterCount);
339             ++m_nWaiterCount;
340             ::LeaveCriticalSection(&m_csectWaiterCount);
341             // This is the actual wait for the signal
342             bool bWaitSucceeded = ::SignalObjectAndWait(m_hndMutex, m_hndSemaphoreSignaller, dwTimeout, FALSE) == WAIT_OBJECT_0;
343             //
344             ::EnterCriticalSection(&m_csectWaiterCount);
345             bool bLastWaiter = --m_nWaiterCount==0 && m_bBroadcastSignalled;
346             ::LeaveCriticalSection(&m_csectWaiterCount);
347
348             // re-acquire the mutex
349             if (bLastWaiter)
350                 ::SignalObjectAndWait(m_hndEventAllWaitersReleased, m_hndMutex, INFINITE, FALSE);
351             else
352                 ::WaitForSingleObject(m_hndMutex, INFINITE);
353             return bWaitSucceeded;
354         }
355
356
357     public:
358
359         inline bool await_signal(timediff td)  { return await_signal_win32((win32_milliseconds(td))); }
360         inline void await_signal()             { await_signal_win32(INFINITE); }
361
362         OSDependentObject() : m_nWaiterCount(0), m_bBroadcastSignalled(false)
363         {
364             EnsureThreadingInitialized();
365             ::InitializeCriticalSection(&m_csectWaiterCount);
366             m_hndEventAllWaitersReleased = ::CreateEvent(
367                     0,      // security
368                     FALSE,  // auto-reset
369                     FALSE,  // initial state non-sognalled
370                     0);     // name
371             m_hndSemaphoreSignaller = ::CreateSemaphore(
372                     0,         // security
373                     0,         // initial count (and will stay this way)
374                     0x100000,  // maximum count (should be as large as the maximum number of waiting threads)
375                     0);        // name
376             m_hndMutex = ::CreateMutex(
377                     0,         // security
378                     FALSE,     // not owned initially
379                     0);        // name
380             //if (m_hndEventAllWaitersReleased==INVALID_HANDLE_VALUE || m_hndSemaphoreSignaller==INVALID_HANDLE_VALUE)
381             //    throw something();
382         }
383
384         ~OSDependentObject()
385         {
386             ::CloseHandle(m_hndMutex);
387             ::CloseHandle(m_hndSemaphoreSignaller);
388             ::CloseHandle(m_hndEventAllWaitersReleased);
389             ::DeleteCriticalSection(&m_csectWaiterCount);
390         }
391
392         inline void signal_unicast()
393         {
394             ::EnterCriticalSection(&m_csectWaiterCount);
395             unsigned int nWaiters = m_nWaiterCount;
396             ::LeaveCriticalSection(&m_csectWaiterCount);
397             if (nWaiters)
398                 ::ReleaseSemaphore(m_hndSemaphoreSignaller, 1, 0);  // release 1 semaphore credit to release one waiting thread
399         }
400
401         void signal_broadcast()
402         {
403             ::EnterCriticalSection(&m_csectWaiterCount);
404             unsigned int nWaiters = m_nWaiterCount;
405             if (nWaiters)
406             {
407                 m_bBroadcastSignalled = true;
408                 ::ReleaseSemaphore(m_hndSemaphoreSignaller, nWaiters, 0);  // release as many credits as there are waiting threads
409                 ::LeaveCriticalSection(&m_csectWaiterCount);
410                 ::WaitForSingleObject(m_hndEventAllWaitersReleased, INFINITE);
411                 // at this point all threads are waiting on m_hndMutex, which would be released outside this function call
412                 m_bBroadcastSignalled = false;
413             }
414             else
415                 // no one is waiting
416                 ::LeaveCriticalSection(&m_csectWaiterCount);
417         }
418         //------------------------------------------------
419         inline void obtain_mutex()    { ::WaitForSingleObject(m_hndMutex, INFINITE); }
420         inline bool tryobtain_mutex() { return ::WaitForSingleObject(m_hndMutex,0) == WAIT_OBJECT_0; }
421         inline void release_mutex()   { ::ReleaseMutex(m_hndMutex); }
422         //------------------------------------------------
423 #endif // OS switch
424     };
425
426     void ThreadConditionSignal::obtain_mutex()
427     {
428         m_osdepobj.obtain_mutex();
429     }
430     bool ThreadConditionSignal::tryobtain_mutex() { return m_osdepobj.tryobtain_mutex(); }
431     void ThreadConditionSignal::release_mutex()
432     {
433         m_osdepobj.release_mutex();
434     }
435
436     void ThreadConditionSignal::await_condition()                   { m_osdepobj.await_signal();  }
437     bool ThreadConditionSignal::await_condition(timediff tdTimeout) { return m_osdepobj.await_signal(tdTimeout);  }
438     void ThreadConditionSignal::signal_condition_single()           { m_osdepobj.signal_unicast();    }
439     void ThreadConditionSignal::signal_condition_broadcast()        { m_osdepobj.signal_broadcast();  }
440
441     ThreadConditionSignal::ThreadConditionSignal() : m_osdepobj(*new OSDependentObject) {}
442     ThreadConditionSignal::~ThreadConditionSignal() { delete &m_osdepobj; }
443
444
445
446
447
448
449
450
451 #if XPLATFORMTHREADS_POSIX
452     namespace // anon
453     {
454         inline int max_FIFO_schedparam()
455         {
456             static const int max_priority = ::sched_get_priority_max(SCHED_FIFO);
457             return max_priority;
458         }
459         inline int schedparam_by_percentage(unsigned short percentage)
460         {
461             return (max_FIFO_schedparam()*10*percentage+500)/1000;
462         }
463         class POSIXThreadPriority
464         {
465         public:
466             int m_SchedPolicy;
467             int m_SchedPriority;
468             POSIXThreadPriority(ThreadPriority pri)
469             {
470                 switch (pri)
471                 {
472                 case ThreadPriority::TimeCritical: m_SchedPolicy=SCHED_FIFO, m_SchedPriority=schedparam_by_percentage(80); break;
473                 case ThreadPriority::AboveNormal:  m_SchedPolicy=SCHED_FIFO, m_SchedPriority=schedparam_by_percentage(20); break;
474                 case ThreadPriority::BelowNormal:  // fall through to normal; nothing is below normal in POSIX
475                 case ThreadPriority::Normal: // fall through to default
476                 default: m_SchedPolicy=SCHED_OTHER, m_SchedPriority=0; break;
477                 }
478             }
479         };
480
481     } // namespace anonymous
482 #endif // XPLATFORMTHREADS_POSIX
483
484 #if XPLATFORMTHREADS_WINDOWS
485     namespace // anon
486     {
487         inline int WinThreadPriority(ThreadPriority pri)
488         {
489             switch (pri)
490             {
491             case ThreadPriority::BelowNormal:  return THREAD_PRIORITY_BELOW_NORMAL;
492             case ThreadPriority::AboveNormal:  return THREAD_PRIORITY_ABOVE_NORMAL;
493             case ThreadPriority::TimeCritical: return THREAD_PRIORITY_TIME_CRITICAL;
494             case ThreadPriority::Normal: // fall through to default
495             default: return THREAD_PRIORITY_NORMAL;
496             }
497         }
498     } // namespace anon
499 #endif // XPLATFORMTHREADS_WINDOWS
500
501
502
503     void SetMyThreadPriority(ThreadPriority pri)
504     {
505 #if XPLATFORMTHREADS_WINDOWS
506         ::SetThreadPriority(::GetCurrentThread(), WinThreadPriority(pri));
507 #endif // XPLATFORMTHREADS_WINDOWS
508 #if XPLATFORMTHREADS_POSIX
509         const POSIXThreadPriority posixpri(pri);
510         sched_param sparam;
511         ::memset(&sparam, 0, sizeof(sparam));
512         sparam.sched_priority = posixpri.m_SchedPriority;
513 #if defined(__linux__)
514         ::sched_setscheduler(0, posixpri.m_SchedPolicy, &sparam);  // linux uses this function instead of pthread_
515 #else
516         pthread_setschedparam(pthread_self(), posixpri.m_SchedPolicy, &sparam);
517 #endif
518 #endif // XPLATFORMTHREADS_POSIX
519     }
520
521
522     struct ThreadWrapperData
523     {
524         ThreadFunction *func;
525         ThreadFunctionArgument arg;
526     };
527
528 #if XPLATFORMTHREADS_WINDOWS
529     static unsigned int __stdcall ThreadWrapper(void * arg)
530     {
531         register ThreadWrapperData *twd = reinterpret_cast<ThreadWrapperData*>(arg);
532         ThreadFunction        *func=twd->func;
533         ThreadFunctionArgument farg=twd->arg;
534         delete twd;
535         return DWORD(func(farg));
536     }
537 #elif XPLATFORMTHREADS_POSIX
538     static void * ThreadWrapper(void *arg)
539     {
540         register ThreadWrapperData *twd = reinterpret_cast<ThreadWrapperData*>(arg);
541         ThreadFunction        *func=twd->func;
542         ThreadFunctionArgument farg=twd->arg;
543         delete twd;
544         return reinterpret_cast<void*>(func(farg));
545     }
546     typedef void*(ThreadWrapperFunction)(void*);
547
548     static ThreadWrapperFunction *ThunkedThreadWrapper = ThreadWrapper;
549
550 #endif // OS switch
551
552
553
554
555
556     class ThreadHandle::OSDependent
557     {
558     public:
559         static void StartThread(ThreadWrapperData *, ThreadHandle &, ThreadPriority);
560         static bool KillThread(ThreadHandle);
561         static bool JoinThread(ThreadHandle, ThreadFunctionReturnType*);
562         static void Close(ThreadHandle);
563 #if XPLATFORMTHREADS_WINDOWS
564         static inline uintptr_t from_oshandle(HANDLE h) { return reinterpret_cast<uintptr_t>(h); }
565         static inline HANDLE to_oshandle(uintptr_t h) { return reinterpret_cast<HANDLE>(h); }
566 #elif XPLATFORMTHREADS_POSIX
567         static inline uintptr_t from_oshandle(pthread_t pt) { return uintptr_t(pt); }
568         static inline pthread_t to_oshandle(uintptr_t h) { return pthread_t(h); }
569 #endif // OS switch
570     };
571
572 #if XPLATFORMTHREADS_WINDOWS
573     const ThreadHandle ThreadHandle::Invalid(OSDependent::from_oshandle(INVALID_HANDLE_VALUE));
574 #elif XPLATFORMTHREADS_POSIX
575     const ThreadHandle ThreadHandle::Invalid(OSDependent::from_oshandle(0));
576 #endif // OS switch
577
578     inline void ThreadHandle::OSDependent::StartThread(ThreadWrapperData *ptwdata, ThreadHandle &th, ThreadPriority pri)
579     {
580 #if XPLATFORMTHREADS_WINDOWS
581         uintptr_t h = ::_beginthreadex(
582                 0,                 // no security attributes, not inheritable
583                 0,                 // default stack size
584                 ThreadWrapper,     // function to call
585                 (void*)(ptwdata),   // argument for function
586                 0,                 // creation flags
587                 0                  // where to store thread ID
588             );
589
590         if (h)
591         {
592             th.m_oshandle = h;
593             if (pri!=ThreadPriority::Normal)
594                 ::SetThreadPriority(to_oshandle(h), WinThreadPriority(pri));
595         }
596         else
597             th=Invalid;
598 #elif XPLATFORMTHREADS_POSIX
599         pthread_attr_t my_thread_attr, *pmy_thread_attr = 0;
600         sched_param my_schedparam;
601
602         if (pri!=ThreadPriority::Normal)
603         {
604             pmy_thread_attr = &my_thread_attr;
605
606             const POSIXThreadPriority posixpriority(pri);
607             int result;
608             result = pthread_attr_init          (pmy_thread_attr);
609             result = pthread_attr_setschedpolicy(pmy_thread_attr, posixpriority.m_SchedPolicy);
610
611             memset(&my_schedparam, 0, sizeof(my_schedparam));
612             my_schedparam.sched_priority = posixpriority.m_SchedPriority;
613             result = pthread_attr_setschedparam(pmy_thread_attr, &my_schedparam);
614         }
615
616         pthread_t pt;
617         int anyerr = pthread_create(
618                 &pt,   // variable for thread handle
619                 pmy_thread_attr,     // default attributes
620                 ThunkedThreadWrapper,
621                 ptwdata
622             );
623
624         if (anyerr)
625             th=Invalid;
626         else
627             th.m_oshandle = OSDependent::from_oshandle(pt);
628 #endif
629     }
630
631     inline bool ThreadHandle::OSDependent::KillThread(ThreadHandle h)
632     {
633 #if XPLATFORMTHREADS_WINDOWS
634         return ::TerminateThread(to_oshandle(h.m_oshandle), (DWORD)-1) != 0;
635 #elif XPLATFORMTHREADS_POSIX
636         return pthread_cancel(to_oshandle(h.m_oshandle)) == 0;
637 #endif
638     }
639
640     bool ThreadHandle::OSDependent::JoinThread(ThreadHandle h, ThreadFunctionReturnType *pretval)
641     {
642 #if XPLATFORMTHREADS_WINDOWS
643         const bool kbReturnedOk = (WAIT_OBJECT_0 == ::WaitForSingleObject(OSDependent::to_oshandle(h.m_oshandle), INFINITE));
644         if (kbReturnedOk && pretval)
645         {
646             DWORD dwExitCode;
647             ::GetExitCodeThread(to_oshandle(h.m_oshandle), &dwExitCode);
648             *pretval = (ThreadFunctionReturnType)(dwExitCode);
649         }
650         return kbReturnedOk;
651 #endif
652 #if XPLATFORMTHREADS_POSIX
653         ThreadFunctionReturnType ptrExitCode = 0;
654         int join_return_code = pthread_join(to_oshandle(h.m_oshandle), (void**)ptrExitCode);
655         const bool kbReturnedOk = (0 == join_return_code);
656         if (0 != pretval)
657         {
658             *pretval = ptrExitCode;
659         }
660         return kbReturnedOk;
661 #endif
662     }
663
664 #if XPLATFORMTHREADS_WINDOWS
665     inline void ThreadHandle::OSDependent::Close(ThreadHandle h)
666     {
667         ::CloseHandle(OSDependent::to_oshandle(h.m_oshandle));
668     }
669 #endif // XPLATFORMTHREADS_WINDOWS
670 #if XPLATFORMTHREADS_POSIX
671     inline void ThreadHandle::OSDependent::Close(ThreadHandle) {}
672 #endif // XPLATFORMTHREADS_POSIX
673
674     //**********************************************************************************************
675
676     class WCThreadRef::OSDependent
677     {
678     public:
679         static void GetCurrentThreadRef(WCThreadRef& tid);
680 #if XPLATFORMTHREADS_WINDOWS
681         static inline uintptr_t from_os(DWORD thread_id) { return (uintptr_t)(thread_id); }
682         static inline DWORD to_os(uintptr_t thread_id)   { return (DWORD)(thread_id); }
683 #elif XPLATFORMTHREADS_POSIX
684     static inline uintptr_t from_os(pthread_t thread_id) { return (uintptr_t)(thread_id); }
685     static inline pthread_t to_os(uintptr_t thread_id)   { return pthread_t(thread_id); }
686 #endif // OS switch
687     };
688
689     //**********************************************************************************************
690     inline void WCThreadRef::OSDependent::GetCurrentThreadRef(WCThreadRef& tid)
691     {
692 #if XPLATFORMTHREADS_WINDOWS
693         DWORD thread_id = ::GetCurrentThreadId();
694         tid.m_osThreadRef = OSDependent::from_os(thread_id);
695
696 #elif XPLATFORMTHREADS_POSIX
697         pthread_t thread_id = ::pthread_self();
698         tid.m_osThreadRef = OSDependent::from_os(thread_id);
699
700 #endif // OS switch
701     }
702
703     //**********************************************************************************************
704
705     ThreadHandle StartThread(ThreadFunction func, ThreadFunctionArgument arg, ThreadPriority thpri)
706     {
707         EnsureThreadingInitialized();
708         ThreadWrapperData *ptwdata = new ThreadWrapperData;
709         ptwdata->func = func;
710         ptwdata->arg  = arg;
711         ThreadHandle thToReturn;
712         ThreadHandle::OSDependent::StartThread(ptwdata, thToReturn, thpri);
713         return thToReturn;
714     }
715
716     bool KillThread(ThreadHandle h)
717     {
718         EnsureThreadingInitialized();
719         return ThreadHandle::OSDependent::KillThread(h);
720     }
721
722     bool JoinThread(ThreadHandle h, ThreadFunctionReturnType *pretval)
723     {
724         EnsureThreadingInitialized();
725         return ThreadHandle::OSDependent::JoinThread(h, pretval);
726     }
727
728     void Close(ThreadHandle h)
729     {
730         EnsureThreadingInitialized();
731         return ThreadHandle::OSDependent::Close(h);
732     }
733
734     //*******************************************************************************************
735
736     WCThreadRef GetCurrentThreadRef()
737     {
738         EnsureThreadingInitialized(); // Is it necessary?
739         WCThreadRef tRefToReturn;
740         WCThreadRef::OSDependent::GetCurrentThreadRef(tRefToReturn);
741         return tRefToReturn;
742     }
743
744     //*******************************************************************************************
745
746     bool IsThreadExists(const WCThreadRef& threadRef)
747     {
748 #if XPLATFORMTHREADS_WINDOWS
749         DWORD dwThreadId = WCThreadRef::OSDependent::to_os((uintptr_t)threadRef);
750         HANDLE handle = ::OpenThread(SYNCHRONIZE, // dwDesiredAccess - use of the thread handle in any of the wait functions
751                                      FALSE,          // bInheritHandle  - processes do not inherit this handle
752                                      dwThreadId);
753
754         // Now we have the handle, check if the associated thread exists:
755         DWORD retVal = WaitForSingleObject(handle, 0);
756         if (retVal == WAIT_FAILED)
757             return false;    // the thread does not exists
758         else
759             return true;    // the thread exists
760
761 #elif XPLATFORMTHREADS_POSIX
762         pthread_t pthreadRef = WCThreadRef::OSDependent::to_os((uintptr_t)threadRef);
763         int retVal = pthread_kill(pthreadRef, 0);    // send a signal to the thread, but do nothing
764         if (retVal == ESRCH)
765             return false;    // the thread does not exists
766         else
767             return true;    // the thread exists
768
769 #endif // OS switch
770     }
771
772     //*******************************************************************************************
773
774     bool operator==(const WCThreadRef& first, const WCThreadRef& second)
775     {
776         return (first.m_osThreadRef == second.m_osThreadRef);
777     }
778
779     bool operator!=(const WCThreadRef& first, const WCThreadRef& second)
780     {
781         return (first.m_osThreadRef != second.m_osThreadRef);
782     }
783
784     bool operator<(const WCThreadRef& first, const WCThreadRef& second)
785     {
786         return (first.m_osThreadRef < second.m_osThreadRef);
787     }
788
789     bool operator>(const WCThreadRef& first, const WCThreadRef& second)
790     {
791         return (first.m_osThreadRef > second.m_osThreadRef);
792     }
793
794     bool WCAtomicLock::obtain(const uint32_t in_num_trys)
795     {
796         bool retVal = false;
797
798         uint32_t timeOut = in_num_trys;
799         while (true)
800         {
801             retVal = g_atomic_int_compare_and_exchange(&m_the_lock, gint(0), gint(1));
802             if (retVal)
803             {
804                 break;
805             }
806             else
807             {
808                 if (--timeOut == 0)
809                 {
810                     break;
811                 }
812                 sleep_milliseconds(1000);
813             }
814         }
815
816         return retVal;
817     }
818
819     void WCAtomicLock::release()
820     {
821         m_the_lock = 0;
822     }
823
824 } //    namespace wvThread
825 } // namespace wvNS {
826