summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcxx/include/thread34
-rw-r--r--libcxx/include/type_traits8
-rw-r--r--libcxx/test/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp20
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
}
OpenPOWER on IntegriCloud