Replace __bind_simple with std:🧵:__make_invoker
* include/std/functional (_Bind_simple, _Bind_simple_helper) (__bind_simple): Remove. * include/std/future: Include <bits/invoke.h> instead of <functional>. (__future_base::_Task_state::_M_run) (__future_base::_Task_state::_M_run_delayed): Use lambda expressions instead of __bind_simple. (__future_base::_Task_state::_S_maybe_wrap_ref): Remove. (async): Use thread::__make_invoker instead of __bind_simple. * include/std/thread: Include <tuple> and <bits/invoke.h> instead of <functional>. (thread::_Invoker, thread::__make_invoker): Define helpers to do INVOKE(DECAY_COPY(f), DECAY_COPY(args)...). From-SVN: r241093
This commit is contained in:
parent
62fdbf29a3
commit
5579170b40
|
@ -1,5 +1,18 @@
|
|||
2016-10-13 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/std/functional (_Bind_simple, _Bind_simple_helper)
|
||||
(__bind_simple): Remove.
|
||||
* include/std/future: Include <bits/invoke.h> instead of <functional>.
|
||||
(__future_base::_Task_state::_M_run)
|
||||
(__future_base::_Task_state::_M_run_delayed): Use lambda expressions
|
||||
instead of __bind_simple.
|
||||
(__future_base::_Task_state::_S_maybe_wrap_ref): Remove.
|
||||
(async): Use thread::__make_invoker instead of __bind_simple.
|
||||
* include/std/thread: Include <tuple> and <bits/invoke.h> instead of
|
||||
<functional>.
|
||||
(thread::_Invoker, thread::__make_invoker): Define helpers to do
|
||||
INVOKE(DECAY_COPY(f), DECAY_COPY(args)...).
|
||||
|
||||
* include/std/functional (_Not_fn): Make exception specifications
|
||||
depend on whether negating the result can throw.
|
||||
* testsuite/20_util/not_fn/1.cc: Move to ...
|
||||
|
|
|
@ -1300,69 +1300,6 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
|
|||
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 _Tp, typename... _Up>
|
||||
explicit
|
||||
_Bind_simple(_Tp&& __f, _Up&&... __args)
|
||||
: _M_bound(std::forward<_Tp>(__f), std::forward<_Up>(__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<std::size_t... _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
|
||||
: _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>
|
||||
{
|
||||
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
|
||||
* operator() is called with an empty target.
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
# include <bits/c++0x_warning.h>
|
||||
#else
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
|
@ -43,6 +42,7 @@
|
|||
#include <atomic>
|
||||
#include <bits/atomic_futex.h>
|
||||
#include <bits/functexcept.h>
|
||||
#include <bits/invoke.h>
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <bits/shared_ptr.h>
|
||||
#include <bits/uses_allocator.h>
|
||||
|
@ -1403,18 +1403,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
virtual void
|
||||
_M_run(_Args&&... __args)
|
||||
{
|
||||
// bound arguments decay so wrap lvalue references
|
||||
auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn),
|
||||
_S_maybe_wrap_ref(std::forward<_Args>(__args))...);
|
||||
auto __boundfn = [&] () -> typename result_of<_Fn(_Args&&...)>::type {
|
||||
return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...);
|
||||
};
|
||||
this->_M_set_result(_S_task_setter(this->_M_result, __boundfn));
|
||||
}
|
||||
|
||||
virtual void
|
||||
_M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self)
|
||||
{
|
||||
// bound arguments decay so wrap lvalue references
|
||||
auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn),
|
||||
_S_maybe_wrap_ref(std::forward<_Args>(__args))...);
|
||||
auto __boundfn = [&] () -> typename result_of<_Fn(_Args&&...)>::type {
|
||||
return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...);
|
||||
};
|
||||
this->_M_set_delayed_result(_S_task_setter(this->_M_result, __boundfn),
|
||||
std::move(__self));
|
||||
}
|
||||
|
@ -1422,17 +1422,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
virtual shared_ptr<_Task_state_base<_Res(_Args...)>>
|
||||
_M_reset();
|
||||
|
||||
template<typename _Tp>
|
||||
static reference_wrapper<_Tp>
|
||||
_S_maybe_wrap_ref(_Tp& __t)
|
||||
{ return std::ref(__t); }
|
||||
|
||||
template<typename _Tp>
|
||||
static
|
||||
typename enable_if<!is_lvalue_reference<_Tp>::value, _Tp>::type&&
|
||||
_S_maybe_wrap_ref(_Tp&& __t)
|
||||
{ return std::forward<_Tp>(__t); }
|
||||
|
||||
struct _Impl : _Alloc
|
||||
{
|
||||
template<typename _Fn2>
|
||||
|
@ -1713,8 +1702,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{
|
||||
__try
|
||||
{
|
||||
__state = __future_base::_S_make_async_state(std::__bind_simple(
|
||||
std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
|
||||
__state = __future_base::_S_make_async_state(
|
||||
std::thread::__make_invoker(std::forward<_Fn>(__fn),
|
||||
std::forward<_Args>(__args)...)
|
||||
);
|
||||
}
|
||||
#if __cpp_exceptions
|
||||
catch(const system_error& __e)
|
||||
|
@ -1727,8 +1718,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
if (!__state)
|
||||
{
|
||||
__state = __future_base::_S_make_deferred_state(std::__bind_simple(
|
||||
std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
|
||||
__state = __future_base::_S_make_deferred_state(
|
||||
std::thread::__make_invoker(std::forward<_Fn>(__fn),
|
||||
std::forward<_Args>(__args)...));
|
||||
}
|
||||
return future<__async_result_of<_Fn, _Args...>>(__state);
|
||||
}
|
||||
|
|
|
@ -36,11 +36,12 @@
|
|||
#else
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <cerrno>
|
||||
#include <bits/functexcept.h>
|
||||
#include <bits/functional_hash.h>
|
||||
#include <bits/invoke.h>
|
||||
#include <bits/gthr.h>
|
||||
|
||||
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
|
||||
|
@ -122,8 +123,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
auto __depend = nullptr;
|
||||
#endif
|
||||
_M_start_thread(_S_make_state(
|
||||
std::__bind_simple(std::forward<_Callable>(__f),
|
||||
std::forward<_Args>(__args)...)),
|
||||
__make_invoker(std::forward<_Callable>(__f),
|
||||
std::forward<_Args>(__args)...)),
|
||||
__depend);
|
||||
}
|
||||
|
||||
|
@ -212,6 +213,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
void
|
||||
_M_start_thread(__shared_base_type);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// A call wrapper that does INVOKE(forwarded tuple elements...)
|
||||
template<typename _Tuple>
|
||||
struct _Invoker
|
||||
{
|
||||
_Tuple _M_t;
|
||||
|
||||
template<size_t _Index>
|
||||
static __tuple_element_t<_Index, _Tuple>&&
|
||||
_S_declval();
|
||||
|
||||
template<size_t... _Ind>
|
||||
auto
|
||||
_M_invoke(_Index_tuple<_Ind...>)
|
||||
noexcept(noexcept(std::__invoke(_S_declval<_Ind>()...)))
|
||||
-> decltype(std::__invoke(_S_declval<_Ind>()...))
|
||||
{ return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
|
||||
|
||||
using _Indices
|
||||
= typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
|
||||
|
||||
using result_type
|
||||
= decltype(std::declval<_Invoker>()._M_invoke(_Indices()));
|
||||
|
||||
result_type
|
||||
operator()()
|
||||
noexcept(noexcept(std::declval<_Invoker>()._M_invoke(_Indices())))
|
||||
{ return _M_invoke(_Indices()); }
|
||||
|
||||
};
|
||||
|
||||
// Alias for _Invoker<tuple<DECAY_COPY(_Tp)...>>
|
||||
template<typename... _Tp>
|
||||
using __invoker_type
|
||||
= _Invoker<decltype(std::make_tuple(std::declval<_Tp>()...))>;
|
||||
|
||||
public:
|
||||
// Returns a call wrapper that does
|
||||
// INVOKE(DECAY_COPY(__callable), DECAY_COPY(__args)).
|
||||
template<typename _Callable, typename... _Args>
|
||||
static __invoker_type<_Callable, _Args...>
|
||||
__make_invoker(_Callable&& __callable, _Args&&... __args)
|
||||
{
|
||||
return { {
|
||||
std::make_tuple(std::forward<_Callable>(__callable),
|
||||
std::forward<_Args>(__args)...)
|
||||
} };
|
||||
}
|
||||
};
|
||||
|
||||
inline void
|
||||
|
|
Loading…
Reference in New Issue