From 5579170b40876cbf8af7a369a7b1ea98e76e8b59 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 13 Oct 2016 11:37:13 +0100 Subject: [PATCH] Replace __bind_simple with std::thread::__make_invoker * include/std/functional (_Bind_simple, _Bind_simple_helper) (__bind_simple): Remove. * include/std/future: Include instead of . (__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 and instead of . (thread::_Invoker, thread::__make_invoker): Define helpers to do INVOKE(DECAY_COPY(f), DECAY_COPY(args)...). From-SVN: r241093 --- libstdc++-v3/ChangeLog | 13 ++++++ libstdc++-v3/include/std/functional | 63 ----------------------------- libstdc++-v3/include/std/future | 36 +++++++---------- libstdc++-v3/include/std/thread | 56 +++++++++++++++++++++++-- 4 files changed, 80 insertions(+), 88 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ffb78ea2f91..d08a8b1d966 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,18 @@ 2016-10-13 Jonathan Wakely + * include/std/functional (_Bind_simple, _Bind_simple_helper) + (__bind_simple): Remove. + * include/std/future: Include instead of . + (__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 and instead of + . + (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 ... diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 58134b7a0e5..38770336c04 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -1300,69 +1300,6 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) std::forward<_BoundArgs>(__args)...); } - template - struct _Bind_simple; - - template - struct _Bind_simple<_Callable(_Args...)> - { - typedef typename result_of<_Callable(_Args...)>::type result_type; - - template - 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::__type _Indices; - return _M_invoke(_Indices()); - } - - private: - template - 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 - struct _Bind_simple_helper - : _Bind_check_arity::type, _BoundArgs...> - { - typedef _Maybe_wrap_member_pointer::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 _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. diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index aa866c5906a..fffbdbb7052 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -35,7 +35,6 @@ # include #else -#include #include #include #include @@ -43,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -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 - static reference_wrapper<_Tp> - _S_maybe_wrap_ref(_Tp& __t) - { return std::ref(__t); } - - template - static - typename enable_if::value, _Tp>::type&& - _S_maybe_wrap_ref(_Tp&& __t) - { return std::forward<_Tp>(__t); } - struct _Impl : _Alloc { template @@ -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); } diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index 7e185d310dd..7a3c4078cc1 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -36,11 +36,12 @@ #else #include -#include #include +#include #include #include #include +#include #include #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 + struct _Invoker + { + _Tuple _M_t; + + template + static __tuple_element_t<_Index, _Tuple>&& + _S_declval(); + + template + 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::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> + template + using __invoker_type + = _Invoker()...))>; + + public: + // Returns a call wrapper that does + // INVOKE(DECAY_COPY(__callable), DECAY_COPY(__args)). + template + 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 -- 2.30.2