1 #include "Threads/WCThreadSafe.h"
4 #if XPLATFORMTHREADS_WINDOWS
5 #define _WIN32_WINNT 0x0500 // need at least Windows2000 (for TryEnterCriticalSection() and SignalObjectAndWait()
6 #include "IncludeWindows.h"
8 #endif // XPLATFORMTHREADS_WINDOWS
11 #if defined(__APPLE__)
12 #include <CoreServices/CoreServices.h>
16 #if XPLATFORMTHREADS_POSIX
17 #include </usr/include/unistd.h> // avoid the framework version and use the /usr/include version
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;
30 #endif //XPLATFORMTHREADS_POSIX
33 static const unsigned int knMicrosecondsPerSecond = 1000*1000;
34 static const unsigned int knNanosecondsPerMicrosecond = 1000;
35 static const unsigned int knNanosecondsPerSecond = knMicrosecondsPerSecond*knNanosecondsPerMicrosecond;
40 //--------------------------------------------------------------------------------
41 static inline bool EnsureThreadingInitialized()
47 //--------------------------------------------------------------------------------
52 //--------------------------------------------------------------------------------
53 static uint32_t CalculateTicksPerMicrosecond();
54 static uint32_t CalculateTicksPerMicrosecond()
56 uint32_t nTicksPerMicrosecond=0;
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;
66 //--------------------- begin measurement code
67 // poll to align to a tick of gettimeofday
68 ::gettimeofday(&tvtmp,0);
70 ::gettimeofday(&tvstart,0);
71 __asm__ __volatile__ (".byte 0x0f, 0x31" : "=A" (Tstart)); // RDTSC
72 } while (tvtmp.tv_usec!=tvstart.tv_usec);
74 ::usleep(sktd_TSC_MeasurementPeriod);
76 ::gettimeofday(&tvtmp,0);
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
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);
87 return nTicksPerMicrosecond;
90 #if defined(__APPLE__) //&& !defined(__MACH__)
93 bool FindNetInterfaceByIPAddress(const char *sIP, char *sInterface) // sIP and sInterface are both char[16]
95 FILE *fProcess , *pSubcall;
96 char sLine[256]="", *pToken, sCommand[150];
100 fProcess = popen("ifconfig -l inet", "r");
103 memset(sInterface, '\0', 16);
104 iret = BSDfread(sLine, sizeof(char), sizeof(sLine), fProcess);
105 pToken = strtok(sLine, " ");
108 sprintf(sCommand, "ifconfig %s | grep \"inet %s \"", pToken, sIP);
110 pSubcall = popen(sCommand, "r");
113 char sSubline[100]="";
114 if (BSDfread(sSubline, sizeof(char), sizeof(sSubline), pSubcall))
117 strcpy(sInterface, pToken);
124 pToken = strtok(NULL, " ");
136 EnsureThreadingInitialized();
137 static const uint32_t nTicksPerMicrosecond = CalculateTicksPerMicrosecond();
139 if (nTicksPerMicrosecond)
142 ::QueryPerformanceCounter(&TSC);
143 return timestamp(uint32_t(TSC.QuadPart/nTicksPerMicrosecond));
145 else return timestamp(0);
146 #elif defined(__APPLE__)
147 if (nTicksPerMicrosecond) {} // prevent 'unused' warnings
149 ::Microseconds(&usecs);
150 return timestamp(usecs.lo);
151 #elif defined(__linux__) && defined(__i386__) && defined(__gnu_linux__)
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
158 #error Dont know how to get microseconds timer !
159 #endif // defined(_WIN32)
163 void sleep_milliseconds(unsigned int nMillisecs)
165 EnsureThreadingInitialized();
166 #if XPLATFORMTHREADS_WINDOWS
168 #elif XPLATFORMTHREADS_POSIX
169 ::usleep(nMillisecs*1000);
171 #error Not implemented for your OS
176 #if XPLATFORMTHREADS_WINDOWS
177 inline DWORD win32_milliseconds(timediff td) { return (td+499)/1000; }
180 void sleep(timediff _td)
184 EnsureThreadingInitialized();
185 #if XPLATFORMTHREADS_WINDOWS
186 ::Sleep(win32_milliseconds(_td)); // This is the best we can do in windows
187 #elif XPLATFORMTHREADS_POSIX
190 #error Not implemented for your OS
196 #if XPLATFORMTHREADS_WINDOWS
197 void yield() { ::Sleep(0); }
198 #elif XPLATFORMTHREADS_POSIX
199 void yield() { ::sched_yield(); }
205 class ThreadMutexInited::OSDependentMutex : public noncopyableobject
207 #if defined (XPLATFORMTHREADS_WINDOWS)
209 CRITICAL_SECTION m_critsec;
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; }
218 #elif defined (XPLATFORMTHREADS_POSIX)
220 pthread_mutex_t m_ptmutex;
222 inline OSDependentMutex()
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);
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; }
238 ThreadMutexInited::ThreadMutexInited() :
241 void ThreadMutexInited::init()
245 m_osdmutex = new OSDependentMutex;
249 void ThreadMutexInited::uninit()
258 ThreadMutexInited::~ThreadMutexInited()
263 void ThreadMutexInited::obtain()
267 m_osdmutex->obtain();
271 void ThreadMutexInited::release()
275 m_osdmutex->release();
279 bool ThreadMutexInited::tryobtain()
284 retVal = m_osdmutex->tryobtain();
289 class ThreadConditionSignal::OSDependentObject : public noncopyableobject
291 #if defined (XPLATFORMTHREADS_POSIX)
294 pthread_cond_t m_ptcond;
295 pthread_mutex_t m_ptmutex;
297 inline OSDependentObject()
299 EnsureThreadingInitialized();
300 ::pthread_mutex_init(&m_ptmutex,0);
301 ::pthread_cond_init(&m_ptcond, 0);
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)
309 timespec tspecDeadline;
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;
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); }
324 #elif XPLATFORMTHREADS_WINDOWS
326 unsigned int m_nWaiterCount;
327 CRITICAL_SECTION m_csectWaiterCount;
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
335 // - - - - - - - - - - - - - - - - - - - - - - - -
336 bool await_signal_win32(DWORD dwTimeout)
338 ::EnterCriticalSection(&m_csectWaiterCount);
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;
344 ::EnterCriticalSection(&m_csectWaiterCount);
345 bool bLastWaiter = --m_nWaiterCount==0 && m_bBroadcastSignalled;
346 ::LeaveCriticalSection(&m_csectWaiterCount);
348 // re-acquire the mutex
350 ::SignalObjectAndWait(m_hndEventAllWaitersReleased, m_hndMutex, INFINITE, FALSE);
352 ::WaitForSingleObject(m_hndMutex, INFINITE);
353 return bWaitSucceeded;
359 inline bool await_signal(timediff td) { return await_signal_win32((win32_milliseconds(td))); }
360 inline void await_signal() { await_signal_win32(INFINITE); }
362 OSDependentObject() : m_nWaiterCount(0), m_bBroadcastSignalled(false)
364 EnsureThreadingInitialized();
365 ::InitializeCriticalSection(&m_csectWaiterCount);
366 m_hndEventAllWaitersReleased = ::CreateEvent(
369 FALSE, // initial state non-sognalled
371 m_hndSemaphoreSignaller = ::CreateSemaphore(
373 0, // initial count (and will stay this way)
374 0x100000, // maximum count (should be as large as the maximum number of waiting threads)
376 m_hndMutex = ::CreateMutex(
378 FALSE, // not owned initially
380 //if (m_hndEventAllWaitersReleased==INVALID_HANDLE_VALUE || m_hndSemaphoreSignaller==INVALID_HANDLE_VALUE)
381 // throw something();
386 ::CloseHandle(m_hndMutex);
387 ::CloseHandle(m_hndSemaphoreSignaller);
388 ::CloseHandle(m_hndEventAllWaitersReleased);
389 ::DeleteCriticalSection(&m_csectWaiterCount);
392 inline void signal_unicast()
394 ::EnterCriticalSection(&m_csectWaiterCount);
395 unsigned int nWaiters = m_nWaiterCount;
396 ::LeaveCriticalSection(&m_csectWaiterCount);
398 ::ReleaseSemaphore(m_hndSemaphoreSignaller, 1, 0); // release 1 semaphore credit to release one waiting thread
401 void signal_broadcast()
403 ::EnterCriticalSection(&m_csectWaiterCount);
404 unsigned int nWaiters = m_nWaiterCount;
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;
416 ::LeaveCriticalSection(&m_csectWaiterCount);
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 //------------------------------------------------
426 void ThreadConditionSignal::obtain_mutex()
428 m_osdepobj.obtain_mutex();
430 bool ThreadConditionSignal::tryobtain_mutex() { return m_osdepobj.tryobtain_mutex(); }
431 void ThreadConditionSignal::release_mutex()
433 m_osdepobj.release_mutex();
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(); }
441 ThreadConditionSignal::ThreadConditionSignal() : m_osdepobj(*new OSDependentObject) {}
442 ThreadConditionSignal::~ThreadConditionSignal() { delete &m_osdepobj; }
451 #if XPLATFORMTHREADS_POSIX
454 inline int max_FIFO_schedparam()
456 static const int max_priority = ::sched_get_priority_max(SCHED_FIFO);
459 inline int schedparam_by_percentage(unsigned short percentage)
461 return (max_FIFO_schedparam()*10*percentage+500)/1000;
463 class POSIXThreadPriority
468 POSIXThreadPriority(ThreadPriority pri)
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;
481 } // namespace anonymous
482 #endif // XPLATFORMTHREADS_POSIX
484 #if XPLATFORMTHREADS_WINDOWS
487 inline int WinThreadPriority(ThreadPriority pri)
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;
499 #endif // XPLATFORMTHREADS_WINDOWS
503 void SetMyThreadPriority(ThreadPriority pri)
505 #if XPLATFORMTHREADS_WINDOWS
506 ::SetThreadPriority(::GetCurrentThread(), WinThreadPriority(pri));
507 #endif // XPLATFORMTHREADS_WINDOWS
508 #if XPLATFORMTHREADS_POSIX
509 const POSIXThreadPriority posixpri(pri);
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_
516 pthread_setschedparam(pthread_self(), posixpri.m_SchedPolicy, &sparam);
518 #endif // XPLATFORMTHREADS_POSIX
522 struct ThreadWrapperData
524 ThreadFunction *func;
525 ThreadFunctionArgument arg;
528 #if XPLATFORMTHREADS_WINDOWS
529 static unsigned int __stdcall ThreadWrapper(void * arg)
531 register ThreadWrapperData *twd = reinterpret_cast<ThreadWrapperData*>(arg);
532 ThreadFunction *func=twd->func;
533 ThreadFunctionArgument farg=twd->arg;
535 return DWORD(func(farg));
537 #elif XPLATFORMTHREADS_POSIX
538 static void * ThreadWrapper(void *arg)
540 register ThreadWrapperData *twd = reinterpret_cast<ThreadWrapperData*>(arg);
541 ThreadFunction *func=twd->func;
542 ThreadFunctionArgument farg=twd->arg;
544 return reinterpret_cast<void*>(func(farg));
546 typedef void*(ThreadWrapperFunction)(void*);
548 static ThreadWrapperFunction *ThunkedThreadWrapper = ThreadWrapper;
556 class ThreadHandle::OSDependent
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); }
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));
578 inline void ThreadHandle::OSDependent::StartThread(ThreadWrapperData *ptwdata, ThreadHandle &th, ThreadPriority pri)
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
587 0 // where to store thread ID
593 if (pri!=ThreadPriority::Normal)
594 ::SetThreadPriority(to_oshandle(h), WinThreadPriority(pri));
598 #elif XPLATFORMTHREADS_POSIX
599 pthread_attr_t my_thread_attr, *pmy_thread_attr = 0;
600 sched_param my_schedparam;
602 if (pri!=ThreadPriority::Normal)
604 pmy_thread_attr = &my_thread_attr;
606 const POSIXThreadPriority posixpriority(pri);
608 result = pthread_attr_init (pmy_thread_attr);
609 result = pthread_attr_setschedpolicy(pmy_thread_attr, posixpriority.m_SchedPolicy);
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);
617 int anyerr = pthread_create(
618 &pt, // variable for thread handle
619 pmy_thread_attr, // default attributes
620 ThunkedThreadWrapper,
627 th.m_oshandle = OSDependent::from_oshandle(pt);
631 inline bool ThreadHandle::OSDependent::KillThread(ThreadHandle h)
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;
640 bool ThreadHandle::OSDependent::JoinThread(ThreadHandle h, ThreadFunctionReturnType *pretval)
642 #if XPLATFORMTHREADS_WINDOWS
643 const bool kbReturnedOk = (WAIT_OBJECT_0 == ::WaitForSingleObject(OSDependent::to_oshandle(h.m_oshandle), INFINITE));
644 if (kbReturnedOk && pretval)
647 ::GetExitCodeThread(to_oshandle(h.m_oshandle), &dwExitCode);
648 *pretval = (ThreadFunctionReturnType)(dwExitCode);
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);
658 *pretval = ptrExitCode;
664 #if XPLATFORMTHREADS_WINDOWS
665 inline void ThreadHandle::OSDependent::Close(ThreadHandle h)
667 ::CloseHandle(OSDependent::to_oshandle(h.m_oshandle));
669 #endif // XPLATFORMTHREADS_WINDOWS
670 #if XPLATFORMTHREADS_POSIX
671 inline void ThreadHandle::OSDependent::Close(ThreadHandle) {}
672 #endif // XPLATFORMTHREADS_POSIX
674 //**********************************************************************************************
676 class WCThreadRef::OSDependent
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); }
689 //**********************************************************************************************
690 inline void WCThreadRef::OSDependent::GetCurrentThreadRef(WCThreadRef& tid)
692 #if XPLATFORMTHREADS_WINDOWS
693 DWORD thread_id = ::GetCurrentThreadId();
694 tid.m_osThreadRef = OSDependent::from_os(thread_id);
696 #elif XPLATFORMTHREADS_POSIX
697 pthread_t thread_id = ::pthread_self();
698 tid.m_osThreadRef = OSDependent::from_os(thread_id);
703 //**********************************************************************************************
705 ThreadHandle StartThread(ThreadFunction func, ThreadFunctionArgument arg, ThreadPriority thpri)
707 EnsureThreadingInitialized();
708 ThreadWrapperData *ptwdata = new ThreadWrapperData;
709 ptwdata->func = func;
711 ThreadHandle thToReturn;
712 ThreadHandle::OSDependent::StartThread(ptwdata, thToReturn, thpri);
716 bool KillThread(ThreadHandle h)
718 EnsureThreadingInitialized();
719 return ThreadHandle::OSDependent::KillThread(h);
722 bool JoinThread(ThreadHandle h, ThreadFunctionReturnType *pretval)
724 EnsureThreadingInitialized();
725 return ThreadHandle::OSDependent::JoinThread(h, pretval);
728 void Close(ThreadHandle h)
730 EnsureThreadingInitialized();
731 return ThreadHandle::OSDependent::Close(h);
734 //*******************************************************************************************
736 WCThreadRef GetCurrentThreadRef()
738 EnsureThreadingInitialized(); // Is it necessary?
739 WCThreadRef tRefToReturn;
740 WCThreadRef::OSDependent::GetCurrentThreadRef(tRefToReturn);
744 //*******************************************************************************************
746 bool IsThreadExists(const WCThreadRef& threadRef)
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
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
759 return true; // the thread exists
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
765 return false; // the thread does not exists
767 return true; // the thread exists
772 //*******************************************************************************************
774 bool operator==(const WCThreadRef& first, const WCThreadRef& second)
776 return (first.m_osThreadRef == second.m_osThreadRef);
779 bool operator!=(const WCThreadRef& first, const WCThreadRef& second)
781 return (first.m_osThreadRef != second.m_osThreadRef);
784 bool operator<(const WCThreadRef& first, const WCThreadRef& second)
786 return (first.m_osThreadRef < second.m_osThreadRef);
789 bool operator>(const WCThreadRef& first, const WCThreadRef& second)
791 return (first.m_osThreadRef > second.m_osThreadRef);
794 bool WCAtomicLock::obtain(const uint32_t in_num_trys)
798 uint32_t timeOut = in_num_trys;
801 retVal = g_atomic_int_compare_and_exchange(&m_the_lock, gint(0), gint(1));
812 sleep_milliseconds(1000);
819 void WCAtomicLock::release()
824 } // namespace wvThread
825 } // namespace wvNS {