Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -902,6 +902,8 @@ defined(__CloudABI__) || \ defined(__sun__) # define _LIBCPP_HAS_THREAD_API_PTHREAD +# elif defined(_LIBCPP_WIN32API) +# define _LIBCPP_HAS_THREAD_API_WIN32 # else # error "No thread API" # endif // _LIBCPP_HAS_THREAD_API Index: include/__threading_support =================================================================== --- include/__threading_support +++ include/__threading_support @@ -47,6 +47,15 @@ defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD) #include #include +#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) +#include +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#include <__debug> +#include #endif #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) @@ -81,6 +90,29 @@ // Thrad Local Storage typedef pthread_key_t __libcpp_tls_key; +#else +// Mutex +typedef SRWLOCK __libcpp_mutex_t; +#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT + +typedef CRITICAL_SECTION __libcpp_recursive_mutex_t; + +// Condition Variable +typedef CONDITION_VARIABLE __libcpp_condvar_t; +#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT + +// Execute Once +typedef INIT_ONCE __libcpp_exec_once_flag; +#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT + +// Thread ID +typedef DWORD __libcpp_thread_id; + +// Thread +typedef HANDLE __libcpp_thread_t; + +// Thread Local Storage +typedef DWORD __libcpp_tls_key; #endif // Mutex @@ -342,6 +374,247 @@ return pthread_setspecific(__key, __p); } +#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) + +// Mutex +_LIBCPP_ALWAYS_INLINE +int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) +{ + InitializeCriticalSection(__m); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) +{ + EnterCriticalSection(__m); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) +{ + TryEnterCriticalSection(__m); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) +{ + LeaveCriticalSection(__m); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) +{ + static_cast(__m); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_lock(__libcpp_mutex_t *__m) +{ + AcquireSRWLockExclusive(__m); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_trylock(__libcpp_mutex_t *__m) +{ + TryAcquireSRWLockExclusive(__m); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) +{ + ReleaseSRWLockExclusive(__m); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) +{ + static_cast(__m); + return 0; +} + +// Condition Variable +_LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) +{ + WakeConditionVariable(__cv); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) +{ + WakeAllConditionVariable(__cv); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) +{ + SleepConditionVariableSRW(__cv, __m, INFINITE, 0); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, + timespec *__ts) +{ + using namespace _VSTD::chrono; + + auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec); + auto abstime = + system_clock::time_point(duration_cast(duration)); + auto timeout_ms = duration_cast(abstime - system_clock::now()); + + _LIBCPP_ASSERT(timeout_ms.count() > INFINITE && "timeout duration overflow"); + if (!SleepConditionVariableSRW(__cv, __m, timeout_ms.count(), 0)) + return GetLastError(); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) +{ + static_cast(__cv); + return 0; +} + +// Execute Once +static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK +__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, + PVOID *__context) +{ + static_cast(__init_once); + static_cast(__context); + + void (*init_routine)(void) = reinterpret_cast(__parameter); + init_routine(); + return TRUE; +} + +int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, + void (*__init_routine)(void)) +{ + if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk, + reinterpret_cast(__init_routine), NULL)) + return GetLastError(); + return 0; +} + +// Thread ID +_LIBCPP_ALWAYS_INLINE +bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, + __libcpp_thread_id __rhs) +{ + return __lhs == __rhs; +} + +_LIBCPP_ALWAYS_INLINE +bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) +{ + return __lhs < __rhs; +} + +// Thread +struct __libcpp_beginthreadex_thunk_data +{ + void *(*__func)(void *); + void *__arg; +}; + +static inline _LIBCPP_ALWAYS_INLINE unsigned int WINAPI +__libcpp_beginthreadex_thunk(void *__data) +{ + __libcpp_beginthreadex_thunk_data data = + *reinterpret_cast<__libcpp_beginthreadex_thunk_data *>(__data); + delete __data; + return reinterpret_cast(data.__func(data.__arg)); +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_thread_create(__libcpp_thread_t *__t, void (*__func)(void *), + void *__arg) +{ + auto *data = new __libcpp_beginthreadex_thunk_data; + data->__func = __func; + data->__arg = __arg; + + *__t = reinterpret_cast(_beginthreadex(NULL, 0, + __libcpp_beginthreadex_thunk, + data, 0, NULL)); + if (*__t) + return 0; + return GetLastError(); +} + +_LIBCPP_ALWAYS_INLINE +__libcpp_thread_id __libcpp_thread_get_current_id() +{ + return GetCurrentThreadId(); +} + +_LIBCPP_ALWAYS_INLINE +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) +{ + return GetThreadId(*__t); +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_thread_join(__libcpp_thread_t *__t) +{ + if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) + return GetLastError(); + if (!CloseHandle(*__t)) + return GetLastError(); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_thread_detach(__libcpp_thread_t *__t) +{ + if (!CloseHandle(*__t)) + return GetLastError(); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_thread_yield() +{ + SwitchToThread(); +} + +// Thread Local Storage +_LIBCPP_ALWAYS_INLINE +int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) +{ + // TODO(compnerd) provide a wrapper for CC adjustment + *__key = FlsAlloc(reinterpret_cast(__at_exit)); + if (*__key == FLS_OUT_OF_INDEXES) + return GetLastError(); + return 0; +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_tls_get(__libcpp_tls_key __key) +{ + return FlsGetValue(__key); +} + +_LIBCPP_ALWAYS_INLINE +int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) +{ + if (!FlsSetValue(__key, __p)) + return GetLastError(); + return 0; +} + #endif // _LIBCPP_HAS_THREAD_API_PTHREAD _LIBCPP_END_NAMESPACE_STD