23 #if defined(ION_PLATFORM_WINDOWS)
24 # define API_DECL WINAPI
31 #if defined(ION_PLATFORM_ASMJS) || defined(ION_PLATFORM_NACL)
32 # define THREAD_NAMING_SUPPORTED 0
34 # define THREAD_NAMING_SUPPORTED 1
55 static ThreadId main_thread_id = kInvalidThreadId;
56 if (
id == kInvalidThreadId) {
57 if (main_thread_id == kInvalidThreadId)
62 return main_thread_id;
69 template <
typename ReturnType>
static ReturnType CastSuccessCode(
bool success) {
70 return static_cast<ReturnType
>(success ? 0 : 1);
72 template <>
void* CastSuccessCode(
bool success) {
73 return reinterpret_cast<void*
>(
static_cast<size_t>(success ? 0 : 1));
77 template <
typename ReturnType>
78 static ReturnType
API_DECL InvokeThreadFuncPtr(
void* arg) {
82 const bool success = (*func_ptr)();
83 return CastSuccessCode<ReturnType>(success);
87 template <
typename ReturnType>
88 static ReturnType
API_DECL InvokeThreadFuncStd(
void* arg) {
92 const bool success = (*func)();
93 return CastSuccessCode<ReturnType>(success);
103 #if defined(ION_PLATFORM_WINDOWS)
106 struct ThreadNameInfo {
107 ThreadNameInfo() :
type(0x1000), flags(0) {}
115 static void CreateThread(
const ThreadFuncPtr func_ptr,
void* arg,
117 if (!::CreateThread(NULL, 0, InvokeThreadFuncPtr<DWORD>, arg, 0,
id))
118 std::cerr <<
"***ION error: Unable to create thread: " << GetLastError()
123 static void CreateThreadStd(
const ThreadStdFunc* func,
void* arg,
125 if (!::CreateThread(NULL, 0, InvokeThreadFuncStd<DWORD>, arg, 0,
id))
126 std::cerr <<
"***ION error: Unable to create thread: " << GetLastError()
140 #if !defined(ION_PLATFORM_WINDOWS)
144 static bool CheckPthreadSuccess(
const char* what,
int result) {
146 #if !defined(ION_COVERAGE) // COV_NF_START
147 std::cerr <<
"Pthread error: " << what <<
" returned "
152 << result <<
": " << strerror(result) <<
"\n";
160 static void CreateThread(
const ThreadFuncPtr func_ptr,
void* arg,
168 static void CreateThreadStd(
const ThreadStdFunc* func,
void* arg,
190 InitMainThreadId(kInvalidThreadId);
194 void* arg =
const_cast<void*
>(
reinterpret_cast<const void*
>(func_ptr));
195 CreateThread(func_ptr, arg, &
id);
203 InitMainThreadId(kInvalidThreadId);
207 void* arg =
const_cast<void*
>(
reinterpret_cast<const void*
>(func));
208 CreateThreadStd(func, arg, &
id);
222 InitMainThreadId(
id);
232 #if defined(ION_PLATFORM_WINDOWS)
235 if (
id != kInvalidThreadId) {
236 if (
const HANDLE
handle = ::OpenThread(THREAD_ALL_ACCESS, 0,
id)) {
237 ::WaitForSingleObject(
handle, INFINITE);
241 std::cerr <<
"***ION error: Could not join thread with ID " <<
id
242 <<
": error " << GetLastError() <<
"\n";
252 bool success =
false;
256 info.name = name.c_str();
259 static const DWORD kMsVcException = 0x406d1388;
260 ::RaiseException(kMsVcException, 0,
sizeof(info) /
sizeof(DWORD),
261 reinterpret_cast<ULONG_PTR*>(&info));
263 } __except(EXCEPTION_CONTINUE_EXECUTION) {
264 std::cerr <<
"***ION error: Unable to name thread with ID "
265 << info.thread_id <<
"\n";
280 if (key == TLS_OUT_OF_INDEXES) {
281 std::cerr <<
"***ION error: Unable to create thread-local storage key: "
282 << GetLastError() <<
"\n";
283 key = kInvalidThreadLocalStorageKey;
289 if (key != kInvalidThreadLocalStorageKey) {
290 if (::TlsSetValue(key, ptr))
292 std::cerr <<
"***ION error: Unable to set thread-local storage pointer: "
293 << GetLastError() <<
"\n";
299 return key == kInvalidThreadLocalStorageKey ? NULL : ::TlsGetValue(key);
303 if (key != kInvalidThreadLocalStorageKey) {
306 std::cerr <<
"***ION error: Unable to delete thread-local storage key: "
307 << GetLastError() <<
"\n";
320 #if !defined(ION_PLATFORM_WINDOWS)
323 if (
id != kInvalidThreadId) {
324 return CheckPthreadSuccess(
"Joining thread", ::
pthread_join(
id, NULL));
330 #if THREAD_NAMING_SUPPORTED
331 static const size_t kMaxThreadNameLength = 16;
334 return kMaxThreadNameLength - 1U;
341 #if THREAD_NAMING_SUPPORTED
342 std::string truncated_name =
name;
344 truncated_name = truncated_name.substr(0, max_len);
345 # if defined(ION_PLATFORM_IOS) || defined(ION_PLATFORM_MAC)
346 return CheckPthreadSuccess(
348 "Naming thread", ::pthread_setname_np(truncated_name.c_str()));
350 return CheckPthreadSuccess(
360 CheckPthreadSuccess(
"Yielding thread", sched_yield());
364 return ::pthread_self();
369 CheckPthreadSuccess(
"Creating thread-local storage key",
370 ::pthread_key_create(&key, NULL));
375 if (key != kInvalidThreadLocalStorageKey) {
376 return CheckPthreadSuccess(
"Setting thread-local storage area",
377 ::pthread_setspecific(key, ptr));
383 return key == kInvalidThreadLocalStorageKey ? NULL :
384 ::pthread_getspecific(key);
388 if (key != kInvalidThreadLocalStorageKey) {
389 return CheckPthreadSuccess(
"Deleting thread-local storage key",
390 ::pthread_key_delete(key));
398 #undef THREAD_NAMING_SUPPORTED
size_t GetMaxThreadNameLength()
Returns the maximum length of a thread name if restricted by the platform.
bool(* ThreadFuncPtr)()
Thread types and constants.
ThreadLocalStorageKey CreateThreadLocalStorageKey()
Thread-local storage functions.
bool IsMainThread()
Returns true if the current thread is the main thread.
#define THREAD_NAMING_SUPPORTED
int pthread_join(pthread_t thread, void **retval)
void YieldThread()
Causes the calling thread to relinquish the CPU if there are other threads waiting to execute...
bool JoinThread(ThreadId id)
Windows-specific public functions.
#define API_DECL
Copyright 2016 Google Inc.
bool SetThreadLocalStorage(ThreadLocalStorageKey key, void *ptr)
Associates ptr with the thread-local storage area indicated by key.
ThreadId SpawnThreadStd(const ThreadStdFunc *func)
pthread_key_t ThreadLocalStorageKey
Defines a type that is used to access thread-local storage.
ThreadId SpawnThread(const ThreadFuncPtr func_ptr)
Platform-independent public functions.
std::function< bool()> ThreadStdFunc
bool IsThreadNamingSupported()
Thread naming functions.
pthread_t ThreadId
Defines a type that can be used to identify a thread.
bool SetThreadName(const std::string &name)
Sets the name of the current thread.
void * GetThreadLocalStorage(ThreadLocalStorageKey key)
Returns the pointer to the thread-local storage area indicated by key.
bool DeleteThreadLocalStorageKey(ThreadLocalStorageKey key)
Deletes a key returned by CreateThreadLocalStorageKey().
void SetMainThreadId(ThreadId id)
Sets the given thread ID to be considered the main thread; IsMainThread() will return true only for t...
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *arg), void *arg)
ThreadId GetCurrentThreadId()
Thread ID functions.