diff options
-rw-r--r-- | libcxx/include/thread | 34 | ||||
-rw-r--r-- | libcxx/include/type_traits | 8 | ||||
-rw-r--r-- | libcxx/test/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp | 20 |
3 files changed, 56 insertions, 6 deletions
diff --git a/libcxx/include/thread b/libcxx/include/thread index 8b3edb7f62d..ca16d213829 100644 --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -95,6 +95,9 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time); #include <system_error> #include <chrono> #include <__mutex_base> +#ifndef _LIBCPP_HAS_NO_VARIADICS +#include <tuple> +#endif #include <pthread.h> #pragma GCC system_header @@ -315,26 +318,35 @@ public: __thread_specific_ptr<__thread_struct>& __thread_local_data(); +#ifndef _LIBCPP_HAS_NO_VARIADICS + +template <class _F, class ..._Args, size_t ..._Indices> +inline _LIBCPP_INLINE_VISIBILITY +void +__threaad_execute(tuple<_F, _Args...>& __t, __tuple_indices<_Indices...>) +{ + _STD::move(_STD::get<0>(__t))(_STD::move(_STD::get<_Indices>(__t))...); +} + template <class _F> void* __thread_proxy(void* __vp) { __thread_local_data().reset(new __thread_struct); std::unique_ptr<_F> __p(static_cast<_F*>(__vp)); - (*__p)(); + typedef typename __make_tuple_indices<tuple_size<_F>::value, 1>::type _Index; + __threaad_execute(*__p, _Index()); return nullptr; } -#ifndef _LIBCPP_HAS_NO_VARIADICS - template <class _F, class ..._Args, class > thread::thread(_F&& __f, _Args&&... __args) { - typedef decltype(bind(std::forward<_F>(__f), std::forward<_Args>(__args)...)) _G; - std::unique_ptr<_G> __p(new _G(bind(std::forward<_F>(__f), - std::forward<_Args>(__args)...))); + typedef tuple<typename decay<_F>::type, typename decay<_Args>::type...> _G; + _STD::unique_ptr<_G> __p(new _G(__decay_copy(_STD::forward<_F>(__f)), + __decay_copy(_STD::forward<_Args>(__args))...)); int __ec = pthread_create(&__t_, 0, &__thread_proxy<_G>, __p.get()); if (__ec == 0) __p.release(); @@ -345,6 +357,16 @@ thread::thread(_F&& __f, _Args&&... __args) #else // _LIBCPP_HAS_NO_VARIADICS template <class _F> +void* +__thread_proxy(void* __vp) +{ + __thread_local_data().reset(new __thread_struct); + std::unique_ptr<_F> __p(static_cast<_F*>(__vp)); + (*__p)(); + return nullptr; +} + +template <class _F> thread::thread(_F __f) { std::unique_ptr<_F> __p(new _F(__f)); diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 5af09e3dbbf..bb93fc36fdc 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1419,6 +1419,14 @@ public: >::type type; }; +template <class _Tp> +inline _LIBCPP_INLINE_VISIBILITY +typename decay<_Tp>::type +__decay_copy(_Tp&& __t) +{ + return _STD::forward<_Tp>(__t); +} + template <class _MP, bool _IsMemberFuctionPtr, bool _IsMemberObjectPtr> struct __member_pointer_traits_imp { diff --git a/libcxx/test/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp b/libcxx/test/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp index f41a70b9cfc..e5568bae29b 100644 --- a/libcxx/test/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp +++ b/libcxx/test/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp @@ -71,6 +71,22 @@ public: int G::n_alive = 0; bool G::op_run = false; +#ifndef _LIBCPP_HAS_NO_VARIADICS + +class MoveOnly +{ + MoveOnly(const MoveOnly&); +public: + MoveOnly() {} + MoveOnly(MoveOnly&&) {} + + void operator()(MoveOnly&&) + { + } +}; + +#endif + int main() { { @@ -126,5 +142,9 @@ int main() assert(G::n_alive == 0); assert(G::op_run); } + { + std::thread t = std::thread(MoveOnly(), MoveOnly()); + t.join(); + } #endif // _LIBCPP_HAS_NO_VARIADICS } |