mirror of git://gcc.gnu.org/git/gcc.git
re PR libstdc++/49668 ([C++0x] std::thread does not forward its args as rvalues)
2011-07-09 Jonathan Wakely <jwakely.gcc@gmail.com> PR libstdc++/49668 * include/std/functional (__bind_simple): Define. * include/std/future (_Task_setter): Parameterize by type of result pointer instead of state object. (_S_task_setter): Type deduction helper. (_Task_state): Use _S_task_setter and __bind_simple. (_Deferred_state, _Async_state): Store call wrapper directly not as std::function. Use _S_task_setter and __bind_simple. (_S_make_deferred_state, _S_make_async_state): Type deduction helpers. (async): Use new functions and __bind_simple. * include/std/mutex (call_once): Use __bind_simple. * include/std/thread (thread): Likewise. Remove unused headers. * src/thread.cc: Add header. * testsuite/30_threads/async/49668.cc: New. * testsuite/30_threads/call_once/49668.cc: New. * testsuite/30_threads/thread/cons/49668.cc: New. * testsuite/30_threads/thread/cons/moveable.cc: Remove unused bool. From-SVN: r176073
This commit is contained in:
parent
4063e61bc6
commit
4880236e3f
|
|
@ -1,3 +1,23 @@
|
||||||
|
2011-07-09 Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||||
|
|
||||||
|
PR libstdc++/49668
|
||||||
|
* include/std/functional (__bind_simple): Define.
|
||||||
|
* include/std/future (_Task_setter): Parameterize by type of result
|
||||||
|
pointer instead of state object.
|
||||||
|
(_S_task_setter): Type deduction helper.
|
||||||
|
(_Task_state): Use _S_task_setter and __bind_simple.
|
||||||
|
(_Deferred_state, _Async_state): Store call wrapper directly not as
|
||||||
|
std::function. Use _S_task_setter and __bind_simple.
|
||||||
|
(_S_make_deferred_state, _S_make_async_state): Type deduction helpers.
|
||||||
|
(async): Use new functions and __bind_simple.
|
||||||
|
* include/std/mutex (call_once): Use __bind_simple.
|
||||||
|
* include/std/thread (thread): Likewise. Remove unused headers.
|
||||||
|
* src/thread.cc: Add header.
|
||||||
|
* testsuite/30_threads/async/49668.cc: New.
|
||||||
|
* testsuite/30_threads/call_once/49668.cc: New.
|
||||||
|
* testsuite/30_threads/thread/cons/49668.cc: New.
|
||||||
|
* testsuite/30_threads/thread/cons/moveable.cc: Remove unused bool.
|
||||||
|
|
||||||
2011-07-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
2011-07-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||||
|
|
||||||
* configure.host (abi_baseline_subdir_switch): Describe.
|
* configure.host (abi_baseline_subdir_switch): Describe.
|
||||||
|
|
|
||||||
|
|
@ -1499,6 +1499,77 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
std::forward<_BoundArgs>(__args)...);
|
std::forward<_BoundArgs>(__args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename _Signature>
|
||||||
|
struct _Bind_simple;
|
||||||
|
|
||||||
|
template<typename _Callable, typename... _Args>
|
||||||
|
struct _Bind_simple<_Callable(_Args...)>
|
||||||
|
{
|
||||||
|
typedef typename result_of<_Callable(_Args...)>::type result_type;
|
||||||
|
|
||||||
|
template<typename... _Args2, typename = typename
|
||||||
|
enable_if< sizeof...(_Args) == sizeof...(_Args2)>::type>
|
||||||
|
explicit
|
||||||
|
_Bind_simple(const _Callable& __callable, _Args2&&... __args)
|
||||||
|
: _M_bound(__callable, std::forward<_Args2>(__args)...)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template<typename... _Args2, typename = typename
|
||||||
|
enable_if< sizeof...(_Args) == sizeof...(_Args2)>::type>
|
||||||
|
explicit
|
||||||
|
_Bind_simple(_Callable&& __callable, _Args2&&... __args)
|
||||||
|
: _M_bound(std::move(__callable), std::forward<_Args2>(__args)...)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
_Bind_simple(const _Bind_simple&) = default;
|
||||||
|
_Bind_simple(_Bind_simple&&) = default;
|
||||||
|
|
||||||
|
result_type
|
||||||
|
operator()()
|
||||||
|
{
|
||||||
|
typedef typename _Build_index_tuple<sizeof...(_Args)>::__type _Indices;
|
||||||
|
return _M_invoke(_Indices());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template<int... _Indices>
|
||||||
|
typename result_of<_Callable(_Args...)>::type
|
||||||
|
_M_invoke(_Index_tuple<_Indices...>)
|
||||||
|
{
|
||||||
|
// std::bind always forwards bound arguments as lvalues,
|
||||||
|
// but this type can call functions which only accept rvalues.
|
||||||
|
return std::forward<_Callable>(std::get<0>(_M_bound))(
|
||||||
|
std::forward<_Args>(std::get<_Indices+1>(_M_bound))...);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<_Callable, _Args...> _M_bound;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename _Func, typename... _BoundArgs>
|
||||||
|
struct _Bind_simple_helper
|
||||||
|
{
|
||||||
|
typedef _Maybe_wrap_member_pointer<typename decay<_Func>::type>
|
||||||
|
__maybe_type;
|
||||||
|
typedef typename __maybe_type::type __func_type;
|
||||||
|
typedef _Bind_simple<__func_type(typename decay<_BoundArgs>::type...)>
|
||||||
|
__type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Simplified version of std::bind for internal use, without support for
|
||||||
|
// unbound arguments, placeholders or nested bind expressions.
|
||||||
|
template<typename _Callable, typename... _Args>
|
||||||
|
typename _Bind_simple_helper<_Callable, _Args...>::__type
|
||||||
|
__bind_simple(_Callable&& __callable, _Args&&... __args)
|
||||||
|
{
|
||||||
|
typedef _Bind_simple_helper<_Callable, _Args...> __helper_type;
|
||||||
|
typedef typename __helper_type::__maybe_type __maybe_type;
|
||||||
|
typedef typename __helper_type::__type __result_type;
|
||||||
|
return __result_type(
|
||||||
|
__maybe_type::__do_wrap( std::forward<_Callable>(__callable)),
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Exception class thrown when class template function's
|
* @brief Exception class thrown when class template function's
|
||||||
* operator() is called with an empty target.
|
* operator() is called with an empty target.
|
||||||
|
|
|
||||||
|
|
@ -488,17 +488,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
virtual void _M_run_deferred() { }
|
virtual void _M_run_deferred() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename _Res>
|
template<typename _BoundFn, typename = typename _BoundFn::result_type>
|
||||||
class _Deferred_state;
|
class _Deferred_state;
|
||||||
|
|
||||||
template<typename _Res>
|
template<typename _BoundFn, typename = typename _BoundFn::result_type>
|
||||||
class _Async_state;
|
class _Async_state;
|
||||||
|
|
||||||
template<typename _Signature>
|
template<typename _Signature>
|
||||||
class _Task_state;
|
class _Task_state;
|
||||||
|
|
||||||
template<typename _StateT, typename _Res = typename _StateT::_Res_type>
|
template<typename _BoundFn>
|
||||||
|
static std::shared_ptr<_State_base>
|
||||||
|
_S_make_deferred_state(_BoundFn&& __fn);
|
||||||
|
|
||||||
|
template<typename _BoundFn>
|
||||||
|
static std::shared_ptr<_State_base>
|
||||||
|
_S_make_async_state(_BoundFn&& __fn);
|
||||||
|
|
||||||
|
template<typename _Res_ptr, typename _Res>
|
||||||
struct _Task_setter;
|
struct _Task_setter;
|
||||||
|
|
||||||
|
template<typename _Res_ptr, typename _BoundFn>
|
||||||
|
class _Task_setter_helper
|
||||||
|
{
|
||||||
|
typedef typename remove_reference<_BoundFn>::type::result_type __res;
|
||||||
|
public:
|
||||||
|
typedef _Task_setter<_Res_ptr, __res> __type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename _Res_ptr, typename _BoundFn>
|
||||||
|
static typename _Task_setter_helper<_Res_ptr, _BoundFn>::__type
|
||||||
|
_S_task_setter(_Res_ptr& __ptr, _BoundFn&& __call)
|
||||||
|
{
|
||||||
|
typedef _Task_setter_helper<_Res_ptr, _BoundFn> __helper_type;
|
||||||
|
typedef typename __helper_type::__type _Setter;
|
||||||
|
return _Setter{ __ptr, std::ref(__call) };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Partial specialization for reference types.
|
/// Partial specialization for reference types.
|
||||||
|
|
@ -1165,29 +1190,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename _StateT, typename _Res>
|
template<typename _Ptr_type, typename _Res>
|
||||||
struct __future_base::_Task_setter
|
struct __future_base::_Task_setter
|
||||||
{
|
{
|
||||||
typename _StateT::_Ptr_type operator()()
|
_Ptr_type operator()()
|
||||||
{
|
{
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
_M_state->_M_result->_M_set(_M_fn());
|
_M_result->_M_set(_M_fn());
|
||||||
}
|
}
|
||||||
__catch(...)
|
__catch(...)
|
||||||
{
|
{
|
||||||
_M_state->_M_result->_M_error = current_exception();
|
_M_result->_M_error = current_exception();
|
||||||
}
|
}
|
||||||
return std::move(_M_state->_M_result);
|
return std::move(_M_result);
|
||||||
}
|
}
|
||||||
_StateT* _M_state;
|
_Ptr_type& _M_result;
|
||||||
std::function<_Res()> _M_fn;
|
std::function<_Res()> _M_fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename _StateT>
|
template<typename _Ptr_type>
|
||||||
struct __future_base::_Task_setter<_StateT, void>
|
struct __future_base::_Task_setter<_Ptr_type, void>
|
||||||
{
|
{
|
||||||
typename _StateT::_Ptr_type operator()()
|
_Ptr_type operator()()
|
||||||
{
|
{
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
|
|
@ -1195,11 +1220,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
__catch(...)
|
__catch(...)
|
||||||
{
|
{
|
||||||
_M_state->_M_result->_M_error = current_exception();
|
_M_result->_M_error = current_exception();
|
||||||
}
|
}
|
||||||
return std::move(_M_state->_M_result);
|
return std::move(_M_result);
|
||||||
}
|
}
|
||||||
_StateT* _M_state;
|
_Ptr_type& _M_result;
|
||||||
std::function<void()> _M_fn;
|
std::function<void()> _M_fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1223,13 +1248,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_M_run(_Args... __args)
|
_M_run(_Args... __args)
|
||||||
{
|
{
|
||||||
// bound arguments decay so wrap lvalue references
|
// bound arguments decay so wrap lvalue references
|
||||||
auto __bound = std::bind<_Res>(std::ref(_M_task),
|
auto __boundfn = std::__bind_simple(std::ref(_M_task),
|
||||||
_S_maybe_wrap_ref(std::forward<_Args>(__args))...);
|
_S_maybe_wrap_ref(std::forward<_Args>(__args))...);
|
||||||
_Task_setter<_Task_state> __setter{ this, std::move(__bound) };
|
auto __setter = _S_task_setter(_M_result, std::move(__boundfn));
|
||||||
_M_set_result(std::move(__setter));
|
_M_set_result(std::move(__setter));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename, typename> friend class _Task_setter;
|
|
||||||
typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type;
|
typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type;
|
||||||
_Ptr_type _M_result;
|
_Ptr_type _M_result;
|
||||||
std::function<_Res(_Args...)> _M_task;
|
std::function<_Res(_Args...)> _M_task;
|
||||||
|
|
@ -1331,40 +1355,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
: public true_type { };
|
: public true_type { };
|
||||||
|
|
||||||
|
|
||||||
template<typename _Res>
|
template<typename _BoundFn, typename _Res>
|
||||||
class __future_base::_Deferred_state : public __future_base::_State_base
|
class __future_base::_Deferred_state : public __future_base::_State_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef _Res _Res_type;
|
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
_Deferred_state(std::function<_Res()>&& __fn)
|
_Deferred_state(_BoundFn&& __fn)
|
||||||
: _M_result(new _Result<_Res>()), _M_fn(std::move(__fn))
|
: _M_result(new _Result<_Res>()), _M_fn(std::move(__fn))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename, typename> friend class _Task_setter;
|
|
||||||
typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type;
|
typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type;
|
||||||
_Ptr_type _M_result;
|
_Ptr_type _M_result;
|
||||||
std::function<_Res()> _M_fn;
|
_BoundFn _M_fn;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
_M_run_deferred()
|
_M_run_deferred()
|
||||||
{
|
{
|
||||||
_Task_setter<_Deferred_state> __setter{ this, _M_fn };
|
|
||||||
// safe to call multiple times so ignore failure
|
// safe to call multiple times so ignore failure
|
||||||
_M_set_result(std::move(__setter), true);
|
_M_set_result(_S_task_setter(_M_result, _M_fn), true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename _Res>
|
template<typename _BoundFn, typename _Res>
|
||||||
class __future_base::_Async_state : public __future_base::_State_base
|
class __future_base::_Async_state : public __future_base::_State_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef _Res _Res_type;
|
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
_Async_state(std::function<_Res()>&& __fn)
|
_Async_state(_BoundFn&& __fn)
|
||||||
: _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)),
|
: _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)),
|
||||||
_M_thread(mem_fn(&_Async_state::_M_do_run), this)
|
_M_thread(mem_fn(&_Async_state::_M_do_run), this)
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -1374,17 +1392,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
private:
|
private:
|
||||||
void _M_do_run()
|
void _M_do_run()
|
||||||
{
|
{
|
||||||
_Task_setter<_Async_state> __setter{ this, std::move(_M_fn) };
|
_M_set_result(_S_task_setter(_M_result, _M_fn));
|
||||||
_M_set_result(std::move(__setter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename, typename> friend class _Task_setter;
|
|
||||||
typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type;
|
typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type;
|
||||||
_Ptr_type _M_result;
|
_Ptr_type _M_result;
|
||||||
std::function<_Res()> _M_fn;
|
_BoundFn _M_fn;
|
||||||
thread _M_thread;
|
thread _M_thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename _BoundFn>
|
||||||
|
inline std::shared_ptr<__future_base::_State_base>
|
||||||
|
__future_base::_S_make_deferred_state(_BoundFn&& __fn)
|
||||||
|
{
|
||||||
|
typedef typename remove_reference<_BoundFn>::type __fn_type;
|
||||||
|
typedef _Deferred_state<__fn_type> __state_type;
|
||||||
|
return std::make_shared<__state_type>(std::move(__fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _BoundFn>
|
||||||
|
inline std::shared_ptr<__future_base::_State_base>
|
||||||
|
__future_base::_S_make_async_state(_BoundFn&& __fn)
|
||||||
|
{
|
||||||
|
typedef typename remove_reference<_BoundFn>::type __fn_type;
|
||||||
|
typedef _Async_state<__fn_type> __state_type;
|
||||||
|
return std::make_shared<__state_type>(std::move(__fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// async
|
/// async
|
||||||
template<typename _Fn, typename... _Args>
|
template<typename _Fn, typename... _Args>
|
||||||
future<typename result_of<_Fn(_Args...)>::type>
|
future<typename result_of<_Fn(_Args...)>::type>
|
||||||
|
|
@ -1394,14 +1429,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
std::shared_ptr<__future_base::_State_base> __state;
|
std::shared_ptr<__future_base::_State_base> __state;
|
||||||
if ((__policy & (launch::async|launch::deferred)) == launch::async)
|
if ((__policy & (launch::async|launch::deferred)) == launch::async)
|
||||||
{
|
{
|
||||||
typedef typename __future_base::_Async_state<result_type> _State;
|
__state = __future_base::_S_make_async_state(std::__bind_simple(
|
||||||
__state = std::make_shared<_State>(std::bind<result_type>(
|
|
||||||
std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
|
std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
typedef typename __future_base::_Deferred_state<result_type> _State;
|
__state = __future_base::_S_make_deferred_state(std::__bind_simple(
|
||||||
__state = std::make_shared<_State>(std::bind<result_type>(
|
|
||||||
std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
|
std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
|
||||||
}
|
}
|
||||||
return future<result_type>(__state);
|
return future<result_type>(__state);
|
||||||
|
|
|
||||||
|
|
@ -801,13 +801,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
|
call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
|
||||||
{
|
{
|
||||||
#ifdef _GLIBCXX_HAVE_TLS
|
#ifdef _GLIBCXX_HAVE_TLS
|
||||||
auto __bound_functor = std::bind<void>(std::forward<_Callable>(__f),
|
auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
|
||||||
std::forward<_Args>(__args)...);
|
std::forward<_Args>(__args)...);
|
||||||
__once_callable = &__bound_functor;
|
__once_callable = &__bound_functor;
|
||||||
__once_call = &__once_call_impl<decltype(__bound_functor)>;
|
__once_call = &__once_call_impl<decltype(__bound_functor)>;
|
||||||
#else
|
#else
|
||||||
unique_lock<mutex> __functor_lock(__get_once_mutex());
|
unique_lock<mutex> __functor_lock(__get_once_mutex());
|
||||||
__once_functor = std::bind<void>(std::forward<_Callable>(__f),
|
__once_functor = std::__bind_simple(std::forward<_Callable>(__f),
|
||||||
std::forward<_Args>(__args)...);
|
std::forward<_Args>(__args)...);
|
||||||
__set_once_functor_lock_ptr(&__functor_lock);
|
__set_once_functor_lock_ptr(&__functor_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,6 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <bits/functexcept.h>
|
#include <bits/functexcept.h>
|
||||||
#include <bits/functional_hash.h>
|
#include <bits/functional_hash.h>
|
||||||
#include <bits/gthr.h>
|
#include <bits/gthr.h>
|
||||||
|
|
@ -132,7 +130,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
explicit
|
explicit
|
||||||
thread(_Callable&& __f, _Args&&... __args)
|
thread(_Callable&& __f, _Args&&... __args)
|
||||||
{
|
{
|
||||||
_M_start_thread(_M_make_routine(std::bind<void>(
|
_M_start_thread(_M_make_routine(std::__bind_simple(
|
||||||
std::forward<_Callable>(__f),
|
std::forward<_Callable>(__f),
|
||||||
std::forward<_Args>(__args)...)));
|
std::forward<_Args>(__args)...)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <system_error>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
|
||||||
#if defined(_GLIBCXX_USE_GET_NPROCS)
|
#if defined(_GLIBCXX_USE_GET_NPROCS)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
|
||||||
|
// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
|
||||||
|
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
|
||||||
|
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
|
||||||
|
// { dg-require-cstdint "" }
|
||||||
|
// { dg-require-gthreads "" }
|
||||||
|
|
||||||
|
// Copyright (C) 2011 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <future>
|
||||||
|
#include <functional>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
|
struct moveable
|
||||||
|
{
|
||||||
|
moveable() = default;
|
||||||
|
moveable(moveable&&) = default;
|
||||||
|
moveable(const moveable&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
using std::launch;
|
||||||
|
namespace ph = std::placeholders;
|
||||||
|
|
||||||
|
typedef decltype(ph::_1) placeholder_type;
|
||||||
|
|
||||||
|
bool f(moveable, placeholder_type) { return true; }
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
auto fut = std::async(launch::async, f, moveable(), ph::_1);
|
||||||
|
bool test = fut.get();
|
||||||
|
VERIFY( test );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test02()
|
||||||
|
{
|
||||||
|
auto fut = std::async(launch::deferred, f, moveable(), ph::_1);
|
||||||
|
bool test = fut.get();
|
||||||
|
VERIFY( test );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
test02();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
|
||||||
|
// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
|
||||||
|
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
|
||||||
|
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
|
||||||
|
// { dg-require-cstdint "" }
|
||||||
|
// { dg-require-gthreads "" }
|
||||||
|
|
||||||
|
// Copyright (C) 2011 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <functional>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
|
struct moveable
|
||||||
|
{
|
||||||
|
moveable() = default;
|
||||||
|
moveable(moveable&&) = default;
|
||||||
|
moveable(const moveable&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef decltype(std::placeholders::_1) placeholder_type;
|
||||||
|
|
||||||
|
void f(moveable, placeholder_type, bool& b) { b = true; }
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
bool test = false;
|
||||||
|
std::once_flag once;
|
||||||
|
std::call_once(once, f, moveable(), std::placeholders::_1, std::ref(test));
|
||||||
|
VERIFY( test );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
|
||||||
|
// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
|
||||||
|
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
|
||||||
|
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
|
||||||
|
// { dg-require-cstdint "" }
|
||||||
|
// { dg-require-gthreads "" }
|
||||||
|
|
||||||
|
// Copyright (C) 2011 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#include <future>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
|
struct moveable
|
||||||
|
{
|
||||||
|
moveable() = default;
|
||||||
|
moveable(moveable&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef decltype(std::placeholders::_1) placeholder_type;
|
||||||
|
|
||||||
|
bool f(moveable, placeholder_type) { return true; }
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
std::packaged_task<bool(moveable, placeholder_type)> p(f);
|
||||||
|
p(moveable(), std::placeholders::_1);
|
||||||
|
bool test = p.get_future().get();
|
||||||
|
VERIFY( test );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
|
||||||
|
// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
|
||||||
|
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
|
||||||
|
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
|
||||||
|
// { dg-require-cstdint "" }
|
||||||
|
// { dg-require-gthreads "" }
|
||||||
|
|
||||||
|
// Copyright (C) 2011 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <functional>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
|
struct moveable
|
||||||
|
{
|
||||||
|
moveable() = default;
|
||||||
|
moveable(moveable&&) = default;
|
||||||
|
moveable(const moveable&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef decltype(std::placeholders::_1) placeholder_type;
|
||||||
|
|
||||||
|
void f(moveable, placeholder_type, bool& b) { b = true; }
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
bool test = false;
|
||||||
|
std::thread t(f, moveable(), std::placeholders::_1, std::ref(test));
|
||||||
|
t.join();
|
||||||
|
VERIFY( test );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// { dg-require-cstdint "" }
|
// { dg-require-cstdint "" }
|
||||||
// { dg-require-gthreads "" }
|
// { dg-require-gthreads "" }
|
||||||
|
|
||||||
// Copyright (C) 2009 Free Software Foundation, Inc.
|
// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
//
|
//
|
||||||
// This file is part of the GNU ISO C++ Library. This library is free
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
// software; you can redistribute it and/or modify it under the
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
|
@ -27,8 +27,6 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <testsuite_hooks.h>
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
bool functor_was_called = false;
|
|
||||||
|
|
||||||
struct moveable
|
struct moveable
|
||||||
{
|
{
|
||||||
moveable() = default;
|
moveable() = default;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue