Brought thread variadic constructor up to current spec, which allows move-only functors and move-only arguments, but disallows functors with non-const lvalue reference parameters.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@131413 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Howard Hinnant 2011-05-16 18:40:35 +00:00
parent ed22f562e5
commit 656bdc3667
3 changed files with 69 additions and 19 deletions

View File

@ -95,6 +95,9 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time);
#include <system_error> #include <system_error>
#include <chrono> #include <chrono>
#include <__mutex_base> #include <__mutex_base>
#ifndef _LIBCPP_HAS_NO_VARIADICS
#include <tuple>
#endif
#include <pthread.h> #include <pthread.h>
#pragma GCC system_header #pragma GCC system_header
@ -315,6 +318,44 @@ public:
__thread_specific_ptr<__thread_struct>& __thread_local_data(); __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));
typedef typename __make_tuple_indices<tuple_size<_F>::value, 1>::type _Index;
__threaad_execute(*__p, _Index());
return nullptr;
}
template <class _F, class ..._Args,
class
>
thread::thread(_F&& __f, _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();
else
__throw_system_error(__ec, "thread constructor failed");
}
#else // _LIBCPP_HAS_NO_VARIADICS
template <class _F> template <class _F>
void* void*
__thread_proxy(void* __vp) __thread_proxy(void* __vp)
@ -325,25 +366,6 @@ __thread_proxy(void* __vp)
return nullptr; 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)...)));
int __ec = pthread_create(&__t_, 0, &__thread_proxy<_G>, __p.get());
if (__ec == 0)
__p.release();
else
__throw_system_error(__ec, "thread constructor failed");
}
#else // _LIBCPP_HAS_NO_VARIADICS
template <class _F> template <class _F>
thread::thread(_F __f) thread::thread(_F __f)
{ {

View File

@ -1419,6 +1419,14 @@ public:
>::type type; >::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> template <class _MP, bool _IsMemberFuctionPtr, bool _IsMemberObjectPtr>
struct __member_pointer_traits_imp struct __member_pointer_traits_imp
{ {

View File

@ -71,6 +71,22 @@ public:
int G::n_alive = 0; int G::n_alive = 0;
bool G::op_run = false; 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() int main()
{ {
{ {
@ -126,5 +142,9 @@ int main()
assert(G::n_alive == 0); assert(G::n_alive == 0);
assert(G::op_run); assert(G::op_run);
} }
{
std::thread t = std::thread(MoveOnly(), MoveOnly());
t.join();
}
#endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_VARIADICS
} }