116#if defined(BLOCXX_HAVE_SCHED_YIELD)
118#elif defined(BLOCXX_WIN32)
126#if defined(BLOCXX_USE_PTHREAD)
128struct LocalThreadParm
135threadStarter(
void* arg)
139 pthread_setcancel(CANCEL_ON);
140 pthread_setasynccancel(CANCEL_OFF);
142 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
143 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
148 int rv = sigfillset(&signalSet);
150 rv = sigdelset(&signalSet, SIGUSR1);
152 rv = pthread_sigmask(SIG_SETMASK, &signalSet, 0);
155 LocalThreadParm* parg =
static_cast<LocalThreadParm*
>(arg);
157 void* funcParm = parg->m_funcParm;
159 Int32 rval = (*func)(funcParm);
160 void* prval =
reinterpret_cast<void*
>(
static_cast<ptrdiff_t
>(rval));
167struct default_stack_size
169#if !defined(BLOCXX_NCR)
174 needsSetting =
false;
179#ifdef _POSIX_THREAD_ATTR_STACKSIZE
180 pthread_attr_t stack_size_attr;
181 if (pthread_attr_init(&stack_size_attr) != 0)
185 if (pthread_attr_getstacksize(&stack_size_attr, &val) != 0)
195#ifdef PTHREAD_STACK_MIN
196 if (PTHREAD_STACK_MIN > val)
198 val = PTHREAD_STACK_MIN;
211 needsSetting =
false;
216#ifdef _POSIX_THREAD_ATTR_STACKSIZE
217 pthread_attr_t stack_size_attr;
218 if (pthread_attr_create(&stack_size_attr) != 0)
223 val = pthread_attr_getstacksize(stack_size_attr);
224 if (
static_cast<signed>(val) == -1)
232#if defined(PTHREAD_STACK_MIN) && defined(_SC_THREAD_STACK_MIN)
233 if (PTHREAD_STACK_MIN > val)
235 val = PTHREAD_STACK_MIN;
245 static bool needsSetting;
248size_t default_stack_size::val = 0;
249bool default_stack_size::needsSetting(
false);
250default_stack_size g_theDefaultStackSize;
252pthread_once_t once_control = PTHREAD_ONCE_INIT;
264SIGUSR1Handler(
int sig)
271static void doOneTimeThreadInitialization()
274 pthread_keycreate(&theKey, NULL);
276 pthread_key_create(&theKey, NULL);
279 struct sigaction temp;
280 memset(&temp,
'\0',
sizeof(temp));
281 sigaction(SIGUSR1, 0, &temp);
282 temp.sa_handler = SIGUSR1Handler;
283 sigemptyset(&temp.sa_mask);
285 sigaction(SIGUSR1, &temp, NULL);
292#if !defined(BLOCXX_NCR)
296 void* funcParm, UInt32 threadFlags)
300 pthread_attr_init(&attr);
303 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
306#if !defined(BLOCXX_VALGRIND_SUPPORT)
308 if (default_stack_size::needsSetting)
310 pthread_attr_setstacksize(&attr, default_stack_size::val);
314 LocalThreadParm* parg =
new LocalThreadParm;
316 parg->m_funcParm = funcParm;
317 cc = pthread_create(&handle, &attr, threadStarter, parg);
318 pthread_attr_destroy(&attr);
326 void* funcParm, UInt32 threadFlags)
330 pthread_attr_create(&attr);
332#if !defined(BLOCXX_VALGRIND_SUPPORT)
334 if (default_stack_size::needsSetting)
336 pthread_attr_setstacksize(&attr, default_stack_size::val);
340 LocalThreadParm* parg =
new LocalThreadParm;
342 parg->m_funcParm = funcParm;
343 if (pthread_create(&handle, attr, threadStarter, parg) != 0)
350 pthread_detach(&handle);
353 pthread_attr_delete(&attr);
362 void* prval =
reinterpret_cast<void*
>(
static_cast<ptrdiff_t
>(rval));
367#if defined(BLOCXX_SIZEOF_PTHREAD_T)
368#if BLOCXX_SIZEOF_PTHREAD_T == 2
369#define BLOCXX_THREAD_CONVERTER UInt16
370#elif BLOCXX_SIZEOF_PTHREAD_T == 4
371#define BLOCXX_THREAD_CONVERTER UInt32
372#elif BLOCXX_SIZEOF_PTHREAD_T == 8
373#define BLOCXX_THREAD_CONVERTER UInt64
376#define BLOCXX_THREAD_CONVERTER UInt16
378#error Unexpected size for pthread_t
382#error No pthread_t size was found!
388 return UInt64(BLOCXX_THREAD_CONVERTER(cma_thread_get_unique(&thr)));
390 return UInt64(BLOCXX_THREAD_CONVERTER(thr));
393#undef BLOCXX_THREAD_CONVERTER
407 int cc = pthread_detach(&handle);
409 int cc = pthread_detach(handle);
426 if ((errno = pthread_join(handle, &prval)) == 0)
428 rval =
static_cast<Int32
>(
reinterpret_cast<ptrdiff_t
>(prval));
441 pthread_once(&once_control, &doOneTimeThreadInitialization);
442 Thread* theThread = NULL;
444 pthread_addr_t addr_ptr = NULL;
445 int ret = pthread_getspecific(theKey, &addr_ptr);
448 theThread =
reinterpret_cast<Thread*
>(addr_ptr);
451 theThread =
reinterpret_cast<Thread*
>(pthread_getspecific(theKey));
457 if (
AtomicGet(theThread->m_cancelRequested) == 1)
464 throw ThreadCancelledException();
471 pthread_once(&once_control, &doOneTimeThreadInitialization);
473 if ((rc = pthread_setspecific(theKey, pTheThread)) != 0)
475 BLOCXX_THROW(ThreadException, Format(
"pthread_setspecific failed. error = %1(%2)", rc, strerror(rc)).c_str());
482 if ((rc = pthread_kill(threadID, signo)) != 0)
484 BLOCXX_THROW(ThreadException, Format(
"pthread_kill failed. error = %1(%2)", rc, strerror(rc)).c_str());
488void cancel(Thread_t threadID)
491 if ((rc = pthread_cancel(threadID)) != 0)
493 BLOCXX_THROW(ThreadException, Format(
"pthread_cancel failed. error = %1(%2)", rc, strerror(rc)).c_str());
498#if defined(BLOCXX_WIN32)
505 BLOCXX_NAMESPACE::Thread* pTheThread;
508typedef Map<DWORD, WThreadInfo> Win32ThreadMap;
509Win32ThreadMap g_threads;
512struct LocalThreadParm
520unsigned __stdcall threadStarter(
void* arg)
522 LocalThreadParm* parg =
reinterpret_cast<LocalThreadParm*
>(arg);
524 void* funcParm = parg->m_funcParm;
526 Int32 rval = (*func)(funcParm);
527 ::_endthreadex(
static_cast<unsigned>(rval));
534addThreadToMap(DWORD threadId, HANDLE threadHandle)
536 MutexLock ml(g_threadsGuard);
538 wi.handle = threadHandle;
540 g_threads[threadId] = wi;
545getThreadHandle(DWORD threadId)
547 MutexLock ml(g_threadsGuard);
549 Win32ThreadMap::iterator it = g_threads.find(threadId);
550 if (it != g_threads.end())
552 chdl = it->second.handle;
559setThreadPointer(DWORD threadId, Thread* pTheThread)
561 MutexLock ml(g_threadsGuard);
562 Win32ThreadMap::iterator it = g_threads.find(threadId);
563 if (it != g_threads.end())
565 it->second.pTheThread = pTheThread;
571removeThreadFromMap(DWORD threadId)
573 MutexLock ml(g_threadsGuard);
575 Win32ThreadMap::iterator it = g_threads.find(threadId);
576 if (it != g_threads.end())
578 chdl = it->second.handle;
586getThreadObject(DWORD threadId)
588 Thread* pTheThread = 0;
589 MutexLock ml(g_threadsGuard);
590 Win32ThreadMap::iterator it = g_threads.find(threadId);
591 if (it != g_threads.end())
593 pTheThread = it->second.pTheThread;
604 void* funcParm, UInt32 threadFlags)
610 LocalThreadParm* parg =
new LocalThreadParm;
612 parg->m_funcParm = funcParm;
613 hThread =
reinterpret_cast<HANDLE
>(::_beginthreadex(NULL, 0, threadStarter,
614 parg, 0, &threadId));
617 addThreadToMap(threadId, hThread);
633 ::_endthreadex(
static_cast<unsigned>(rval));
641 BLOCXX_ASSERTMSG(
sizeof(
unsigned long) >=
sizeof(Thread_t),
" Thread_t truncated!");
642 return static_cast<UInt64
>(thr);
650 HANDLE thdl = removeThreadFromMap(threadId);
671 HANDLE thdl = getThreadHandle(threadId);
674 if (::WaitForSingleObject(thdl, INFINITE) != WAIT_FAILED)
676 if (::GetExitCodeThread(thdl, &rval) != 0)
678 rvalArg =
static_cast<Int32
>(rval);
691 Thread* pTheThread = getThreadObject(threadId);
694 if (
AtomicGet(pTheThread->m_cancelRequested) == 1)
701 throw ThreadCancelledException();
708 Thread* pThread =
static_cast<Thread*
>(pThreadArg);
709 DWORD threadId = pThread->getId();
710 setThreadPointer(threadId, pThread);
717void cancel(Thread_t threadId)
719 HANDLE thdl = getThreadHandle(threadId);
722 ::TerminateThread(thdl, -1);