Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -882,6 +882,8 @@ defined(__CloudABI__) || \ defined(__sun__) # define _LIBCPP_HAS_THREAD_API_PTHREAD +# elif defined(_WIN32) +# 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 @@ -32,9 +32,20 @@ #include <__external_threading> #else +#if !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && \ + !defined(_LIBCPP_HAS_THREAD_API_WIN32) +#error "unknown threading model" +#endif + #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) #include #include +#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) +#define WIN32_LEAN_AND_MEAN +#define VC_EXTRA_LEAN +#include +#include +#include #endif #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) @@ -62,6 +73,23 @@ // Thrad Local Storage typedef pthread_key_t __libcpp_tls_key; +#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) +// Mutex +typedef SRWLOCK __libcpp_mutex_t; +#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT + +// Condition Variable +typedef CONDITION_VARIABLE __libcpp_condvar_t; +#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT + +// Thread ID +typedef DWORD __libcpp_thread_id; + +// Thread +typedef HANDLE __libcpp_thread_t; + +// Thread Local Storage +typedef DWORD __libcpp_tls_key; #endif // Mutex @@ -267,6 +295,150 @@ pthread_setspecific(__key, __p); } +#elif defined(_LIBCPP_HAS_THREAD_API_WIN32) + +// Mutex +int __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m) +{ + InitializeSRWLock(__m); + return 0; +} + +int __libcpp_mutex_lock(__libcpp_mutex_t *__m) +{ + AcquireSRWLockExclusive(__m); + return 0; +} + +int __libcpp_mutex_trylock(__libcpp_mutex_t *__m) +{ + return TryAcquireSRWLockExclusive(__m); +} + +int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) +{ + ReleaseSRWLockExclusive(__m); + return 0; +} + +int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) +{ + static_cast(__m); + return 0; +} + +// Condition Variable +int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) +{ + WakeConditionVariable(__cv); + return 0; +} + +int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) +{ + WakeAllConditionVariable(__cv); + return 0; +} + +int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) +{ + SleepConditionVariableSRW(__cv, __m, INFINITE, 0); + return 0; +} + +int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, + timespec *__ts) +{ + using namespace _VSTD::chrono; + auto timeout = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec); + // TODO(compnerd) handle timeouts < 10ms + // TODO(compnerd) handle spurious timeout + if (!SleepConditionVariableSRW(__cv, __m, + duration_cast(timeout).count(), + 0)) + return GetLastError(); + return 0; +} + +int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) +{ + static_cast(__cv); + return 0; +} + +// Thread ID +bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, + __libcpp_thread_id __rhs) +{ + return __lhs == __rhs; +} + +bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) +{ + return __lhs < __rhs; +} + +// Thread +int __libcpp_thread_create(__libcpp_thread_t *__t, + unsigned int (* WINAPI __func)(void *), void *__arg) +{ + *__t = + reinterpret_cast(_beginthreadex(NULL, 0, __func, __arg, 0, NULL)); + if (*__t) + return 0; + return GetLastError(); +} + +__libcpp_thread_id __libcpp_thread_get_current_id() +{ + return GetCurrentThreadId(); +} + +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) +{ + return GetThreadId(*__t); +} + +int __libcpp_thread_join(__libcpp_thread_t *__t) +{ + if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) + return GetLastError(); + if (!CloseHandle(*__t)) + return GetLastError(); + return 0; +} + +int __libcpp_thread_detach(__libcpp_thread_t *__t) +{ + if (!CloseHandle(*__t)) + return GetLastError(); + return 0; +} + +void __libcpp_thread_yield() +{ + SwitchToThread(); +} + +// Thread Local Storage +int __libcpp_tls_create(__libcpp_tls_key *__key, void (* WINAPI __at_exit)(void *)) +{ + *__key = FlsAlloc(__at_exit); + if (*__key == FLS_OUT_OF_INDEXES) + return GetLastError(); + return 0; +} + +void *__libcpp_tls_get(__libcpp_tls_key __key) +{ + return FlsGetValue(__key); +} + +void __libcpp_tls_set(__libcpp_tls_key __key, void *__p) +{ + FlsSetValue(__key, __p); +} + #endif // _LIBCPP_HAS_THREAD_API_PTHREAD _LIBCPP_END_NAMESPACE_STD