summaryrefslogtreecommitdiff
path: root/include/thread
diff options
context:
space:
mode:
Diffstat (limited to 'include/thread')
-rw-r--r--include/thread93
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