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:
Jonathan Wakely 2016-10-13 11:37:13 +01:00 committed by Jonathan Wakely
parent 62fdbf29a3
commit 5579170b40
4 changed files with 80 additions and 88 deletions

View File

@ -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 ...

View File

@ -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.

View File

@ -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);
}

View File

@ -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