diff options
Diffstat (limited to 'include/thread')
-rw-r--r-- | include/thread | 93 |
1 files changed, 54 insertions, 39 deletions
diff --git a/include/thread b/include/thread index 6857e9edb68b..022021c5adde 100644 --- a/include/thread +++ b/include/thread @@ -98,8 +98,7 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time); #ifndef _LIBCPP_HAS_NO_VARIADICS #include <tuple> #endif -#include <pthread.h> -#include <sched.h> +#include <__threading_support> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -137,7 +136,7 @@ public: template <class _Tp> class __thread_specific_ptr { - pthread_key_t __key_; + __libcpp_tl_key __key_; // Only __thread_local_data() may construct a __thread_specific_ptr // and only with _Tp == __thread_struct. @@ -155,7 +154,7 @@ public: ~__thread_specific_ptr(); _LIBCPP_INLINE_VISIBILITY - pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));} + pointer get() const {return static_cast<_Tp*>(__libcpp_tl_get(__key_));} _LIBCPP_INLINE_VISIBILITY pointer operator*() const {return *get();} _LIBCPP_INLINE_VISIBILITY @@ -174,12 +173,12 @@ __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) template <class _Tp> __thread_specific_ptr<_Tp>::__thread_specific_ptr() { - int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit); -#ifndef _LIBCPP_NO_EXCEPTIONS + int __ec = __libcpp_tl_create( + &__key_, + &__thread_specific_ptr::__at_thread_exit); if (__ec) - throw system_error(error_code(__ec, system_category()), + __throw_system_error(__ec, "__thread_specific_ptr construction failed"); -#endif } template <class _Tp> @@ -196,7 +195,7 @@ typename __thread_specific_ptr<_Tp>::pointer __thread_specific_ptr<_Tp>::release() { pointer __p = get(); - pthread_setspecific(__key_, 0); + __libcpp_tl_set(__key_, nullptr); return __p; } @@ -205,7 +204,7 @@ void __thread_specific_ptr<_Tp>::reset(pointer __p) { pointer __p_old = get(); - pthread_setspecific(__key_, __p); + __libcpp_tl_set(__key_, __p); delete __p_old; } @@ -219,14 +218,14 @@ _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; } // this_thread -template<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; +template<> struct hash<__thread_id>; class _LIBCPP_TYPE_VIS_ONLY __thread_id { // FIXME: pthread_t is a pointer on Darwin but a long on Linux. // NULL is the no-thread value on Darwin. Someone needs to check // on other platforms. We assume 0 works everywhere for now. - pthread_t __id_; + __libcpp_thread_id __id_; public: _LIBCPP_INLINE_VISIBILITY @@ -234,13 +233,13 @@ public: friend _LIBCPP_INLINE_VISIBILITY bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT - {return __x.__id_ == __y.__id_;} + {return __libcpp_thread_id_equal(__x.__id_, __y.__id_);} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__x == __y);} friend _LIBCPP_INLINE_VISIBILITY bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __x.__id_ < __y.__id_;} + {return __libcpp_thread_id_less(__x.__id_, __y.__id_);} friend _LIBCPP_INLINE_VISIBILITY bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__y < __x);} @@ -260,7 +259,7 @@ public: private: _LIBCPP_INLINE_VISIBILITY - __thread_id(pthread_t __id) : __id_(__id) {} + __thread_id(__libcpp_thread_id __id) : __id_(__id) {} friend __thread_id this_thread::get_id() _NOEXCEPT; friend class _LIBCPP_TYPE_VIS thread; @@ -274,7 +273,7 @@ struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id> _LIBCPP_INLINE_VISIBILITY size_t operator()(__thread_id __v) const { - return hash<pthread_t>()(__v.__id_); + return hash<__libcpp_thread_id>()(__v.__id_); } }; @@ -285,20 +284,20 @@ inline _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT { - return pthread_self(); + return __libcpp_thread_get_current_id(); } } // this_thread class _LIBCPP_TYPE_VIS thread { - pthread_t __t_; + __libcpp_thread_t __t_; thread(const thread&); thread& operator=(const thread&); public: typedef __thread_id id; - typedef pthread_t native_handle_type; + typedef __libcpp_thread_t native_handle_type; _LIBCPP_INLINE_VISIBILITY thread() _NOEXCEPT : __t_(0) {} @@ -330,7 +329,7 @@ public: void join(); void detach(); _LIBCPP_INLINE_VISIBILITY - id get_id() const _NOEXCEPT {return __t_;} + id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() _NOEXCEPT {return __t_;} @@ -339,21 +338,21 @@ public: #ifndef _LIBCPP_HAS_NO_VARIADICS -template <class _Fp, class ..._Args, size_t ..._Indices> +template <class _TSp, class _Fp, class ..._Args, size_t ..._Indices> inline _LIBCPP_INLINE_VISIBILITY void -__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>) +__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) { - __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); + __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); } template <class _Fp> -void* -__thread_proxy(void* __vp) +void* __thread_proxy(void* __vp) { - __thread_local_data().reset(new __thread_struct); + // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...> std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); - typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; + __thread_local_data().reset(_VSTD::get<0>(*__p).release()); + typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; __thread_execute(*__p, _Index()); return nullptr; } @@ -363,10 +362,14 @@ template <class _Fp, class ..._Args, > thread::thread(_Fp&& __f, _Args&&... __args) { - typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; - _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)), - __decay_copy(_VSTD::forward<_Args>(__args))...)); - int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); + typedef unique_ptr<__thread_struct> _TSPtr; + _TSPtr __tsp(new __thread_struct); + typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; + _VSTD::unique_ptr<_Gp> __p( + new _Gp(std::move(__tsp), + __decay_copy(_VSTD::forward<_Fp>(__f)), + __decay_copy(_VSTD::forward<_Args>(__args))...)); + int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); if (__ec == 0) __p.release(); else @@ -376,22 +379,34 @@ thread::thread(_Fp&& __f, _Args&&... __args) #else // _LIBCPP_HAS_NO_VARIADICS template <class _Fp> -void* -__thread_proxy(void* __vp) +struct __thread_invoke_pair { + // This type is used to pass memory for thread local storage and a functor + // to a newly created thread because std::pair doesn't work with + // std::unique_ptr in C++03. + __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} + unique_ptr<__thread_struct> __tsp_; + _Fp __fn_; +}; + +template <class _Fp> +void* __thread_proxy_cxx03(void* __vp) { - __thread_local_data().reset(new __thread_struct); std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); - (*__p)(); + __thread_local_data().reset(__p->__tsp_.release()); + (__p->__fn_)(); return nullptr; } template <class _Fp> thread::thread(_Fp __f) { - std::unique_ptr<_Fp> __p(new _Fp(__f)); - int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get()); + + typedef __thread_invoke_pair<_Fp> _InvokePair; + typedef std::unique_ptr<_InvokePair> _PairPtr; + _PairPtr __pp(new _InvokePair(__f)); + int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); if (__ec == 0) - __p.release(); + __pp.release(); else __throw_system_error(__ec, "thread constructor failed"); } @@ -464,7 +479,7 @@ sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) } inline _LIBCPP_INLINE_VISIBILITY -void yield() _NOEXCEPT {sched_yield();} +void yield() _NOEXCEPT {__libcpp_thread_yield();} } // this_thread |