aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/std/future
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2020-08-18 14:23:19 +0100
committerJonathan Wakely <jwakely@redhat.com>2020-08-18 14:28:38 +0100
commitbb1b7f087bdd028000fd8f84e74b20adccc9d5bb (patch)
tree65bdb476307e00f202d1de0f0b1d649342d4788e /libstdc++-v3/include/std/future
parent634046d1a81b48a48b3564ff2f90974f6b7b087b (diff)
downloadgcc-bb1b7f087bdd028000fd8f84e74b20adccc9d5bb.zip
gcc-bb1b7f087bdd028000fd8f84e74b20adccc9d5bb.tar.gz
gcc-bb1b7f087bdd028000fd8f84e74b20adccc9d5bb.tar.bz2
libstdc++: Remove redundant copying of std::async arguments [PR 69724]
As was previously done for std::thread, this removes an unnecessary copy of an rvalue of type thread::_Invoker. Instead of creating the rvalue and then moving that into the shared state, the member of the shared state is initialized directly from the forwarded callable and bound arguments. This also slightly simplifies std::thread creation to remove the _S_make_state helper function. libstdc++-v3/ChangeLog: PR libstdc++/69724 * include/std/future (__future_base::_S_make_deferred_state) (__future_base::_S_make_async_state): Remove. (__future_base::_Deferred_state): Change constructor to accept a parameter pack of arguments and forward them to the call wrapper. (__future_base::_Async_state_impl): Likewise. Replace lambda expression with a named member function. (async): Construct state object directly from the arguments, instead of using thread::__make_invoker, _S_make_deferred_state and _S_make_async_state. Move shared state into the returned future. * include/std/thread (thread::_Call_wrapper): New alias template for use by constructor and std::async. (thread::thread(Callable&&, Args&&...)): Create state object directly instead of using _S_make_state. (thread::__make_invoker, thread::__decayed_tuple) (thread::_S_make_state): Remove. * testsuite/30_threads/async/69724.cc: New test.
Diffstat (limited to 'libstdc++-v3/include/std/future')
-rw-r--r--libstdc++-v3/include/std/future101
1 files changed, 44 insertions, 57 deletions
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index bdf4a75..e0816c2 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -605,14 +605,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Fn, typename _Alloc, typename _Signature>
class _Task_state;
- 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 _Fn,
typename _Res = typename _Res_ptr::element_type::result_type>
struct _Task_setter;
@@ -1614,10 +1606,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __future_base::_State_base
{
public:
- explicit
- _Deferred_state(_BoundFn&& __fn)
- : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn))
- { }
+ template<typename... _Args>
+ explicit
+ _Deferred_state(_Args&&... __args)
+ : _M_result(new _Result<_Res>()),
+ _M_fn{{std::forward<_Args>(__args)...}}
+ { }
private:
typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type;
@@ -1679,69 +1673,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __future_base::_Async_state_commonV2
{
public:
- explicit
- _Async_state_impl(_BoundFn&& __fn)
- : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn))
- {
- _M_thread = std::thread{ [this] {
- __try
- {
- _M_set_result(_S_task_setter(_M_result, _M_fn));
- }
- __catch (const __cxxabiv1::__forced_unwind&)
- {
- // make the shared state ready on thread cancellation
- if (static_cast<bool>(_M_result))
- this->_M_break_promise(std::move(_M_result));
- __throw_exception_again;
- }
- } };
- }
+ template<typename... _Args>
+ explicit
+ _Async_state_impl(_Args&&... __args)
+ : _M_result(new _Result<_Res>()),
+ _M_fn{{std::forward<_Args>(__args)...}}
+ {
+ _M_thread = std::thread{&_Async_state_impl::_M_run, this};
+ }
// Must not destroy _M_result and _M_fn until the thread finishes.
// Call join() directly rather than through _M_join() because no other
// thread can be referring to this state if it is being destroyed.
- ~_Async_state_impl() { if (_M_thread.joinable()) _M_thread.join(); }
+ ~_Async_state_impl()
+ {
+ if (_M_thread.joinable())
+ _M_thread.join();
+ }
private:
+ void
+ _M_run()
+ {
+ __try
+ {
+ _M_set_result(_S_task_setter(_M_result, _M_fn));
+ }
+ __catch (const __cxxabiv1::__forced_unwind&)
+ {
+ // make the shared state ready on thread cancellation
+ if (static_cast<bool>(_M_result))
+ this->_M_break_promise(std::move(_M_result));
+ __throw_exception_again;
+ }
+ }
+
typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type;
_Ptr_type _M_result;
_BoundFn _M_fn;
};
- 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_impl<__fn_type> __state_type;
- return std::make_shared<__state_type>(std::move(__fn));
- }
-
/// async
template<typename _Fn, typename... _Args>
_GLIBCXX_NODISCARD future<__async_result_of<_Fn, _Args...>>
async(launch __policy, _Fn&& __fn, _Args&&... __args)
{
+ using _Wr = std::thread::_Call_wrapper<_Fn, _Args...>;
+ using _As = __future_base::_Async_state_impl<_Wr>;
+ using _Ds = __future_base::_Deferred_state<_Wr>;
+
std::shared_ptr<__future_base::_State_base> __state;
if ((__policy & launch::async) == launch::async)
{
__try
{
- __state = __future_base::_S_make_async_state(
- std::thread::__make_invoker(std::forward<_Fn>(__fn),
- std::forward<_Args>(__args)...)
- );
+ __state = std::make_shared<_As>(std::forward<_Fn>(__fn),
+ std::forward<_Args>(__args)...);
}
#if __cpp_exceptions
catch(const system_error& __e)
@@ -1754,11 +1742,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
if (!__state)
{
- __state = __future_base::_S_make_deferred_state(
- std::thread::__make_invoker(std::forward<_Fn>(__fn),
- std::forward<_Args>(__args)...));
+ __state = std::make_shared<_Ds>(std::forward<_Fn>(__fn),
+ std::forward<_Args>(__args)...);
}
- return future<__async_result_of<_Fn, _Args...>>(__state);
+ return future<__async_result_of<_Fn, _Args...>>(std::move(__state));
}
/// async, potential overload