commit 09c2fd279f76b886efa8bdb0b9b2dcb0956ab7f5 Author: Jonathan Wakely Date: Sat May 17 14:09:40 2014 +0100 * include/std/future (_State_baseV2::_M_set_result): Pass pointers to _M_do_set. (_State_baseV2::_M_do_set): Change parameters to pointers. (_State_baseV2::_Setter): Change _M_arg from reference to pointer. (_State_baseV2::__setter): Initialize _Setter with pointers. (_State_baseV2::__setter(promise*)): Remove overload. (promise::set_value, promise::set_exception): Pass setter directly to _M_set_result. (_State_baseV2::_Task_setter): Add template parameter for callable type and replace std::function member with pointer to that type. Change _M_result member from reference to pointer. (_State_baseV2::_S_task_setter): Change parameter to lvalue reference and initialize _Task_setter with pointers. (__location_invariant): Specialize for _Setter and _Task_setter. diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index be2ed96..c3aaaec 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -358,7 +358,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // all calls to this function are serialized, // side-effects of invoking __res only happen once call_once(_M_once, &_State_baseV2::_M_do_set, this, - ref(__res), ref(__lock)); + std::__addressof(__res), std::__addressof(__lock)); if (__lock.owns_lock()) _M_cond.notify_all(); else if (!__ignore_failure) @@ -396,19 +396,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct _Setter<_Res, _Arg&> { // check this is only used by promise::set_value(const R&) - // or promise::set_value(R&) + // or promise::set_value(R&) static_assert(is_same<_Res, _Arg&>::value // promise - || is_same::value, // promise + || is_same::value, // promise "Invalid specialisation"); typename promise<_Res>::_Ptr_type operator()() { _State_baseV2::_S_check(_M_promise->_M_future); - _M_promise->_M_storage->_M_set(_M_arg); + _M_promise->_M_storage->_M_set(*_M_arg); return std::move(_M_promise->_M_storage); } promise<_Res>* _M_promise; - _Arg& _M_arg; + _Arg* _M_arg; }; // set rvalues @@ -418,11 +418,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename promise<_Res>::_Ptr_type operator()() { _State_baseV2::_S_check(_M_promise->_M_future); - _M_promise->_M_storage->_M_set(std::move(_M_arg)); + _M_promise->_M_storage->_M_set(std::move(*_M_arg)); return std::move(_M_promise->_M_storage); } promise<_Res>* _M_promise; - _Res& _M_arg; + _Res* _M_arg; }; struct __exception_ptr_tag { }; @@ -434,31 +434,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename promise<_Res>::_Ptr_type operator()() { _State_baseV2::_S_check(_M_promise->_M_future); - _M_promise->_M_storage->_M_error = _M_ex; + _M_promise->_M_storage->_M_error = *_M_ex; return std::move(_M_promise->_M_storage); } promise<_Res>* _M_promise; - exception_ptr& _M_ex; + exception_ptr* _M_ex; }; template static _Setter<_Res, _Arg&&> __setter(promise<_Res>* __prom, _Arg&& __arg) { - return _Setter<_Res, _Arg&&>{ __prom, __arg }; + return _Setter<_Res, _Arg&&>{ __prom, &__arg }; } template static _Setter<_Res, __exception_ptr_tag> __setter(exception_ptr& __ex, promise<_Res>* __prom) { - return _Setter<_Res, __exception_ptr_tag>{ __prom, __ex }; + return _Setter<_Res, __exception_ptr_tag>{ __prom, &__ex }; } - static _Setter - __setter(promise* __prom); - template static void _S_check(const shared_ptr<_Tp>& __p) @@ -469,10 +466,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: void - _M_do_set(function<_Ptr_type()>& __f, unique_lock& __lock) + _M_do_set(function<_Ptr_type()>* __f, unique_lock* __lock) { - _Ptr_type __res = __f(); // do not hold lock while running setter - __lock.lock(); + _Ptr_type __res = (*__f)(); // do not hold lock while running setter + __lock->lock(); _M_result.swap(__res); } @@ -514,15 +511,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static std::shared_ptr<_State_base> _S_make_async_state(_BoundFn&& __fn); - template struct _Task_setter; template - static _Task_setter<_Res_ptr> - _S_task_setter(_Res_ptr& __ptr, _BoundFn&& __call) + static _Task_setter<_Res_ptr, _BoundFn> + _S_task_setter(_Res_ptr& __ptr, _BoundFn& __call) { - return _Task_setter<_Res_ptr>{ __ptr, std::ref(__call) }; + return { std::__addressof(__ptr), std::__addressof(__call) }; } }; @@ -554,6 +551,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_destroy() { delete this; } }; + // Allow _Setter objects to be stored locally in std::function + template + struct __is_location_invariant + <__future_base::_State_base::_Setter<_Res, _Arg>> + : true_type { }; + + // Allow _Task_setter objects to be stored locally in std::function + template + struct __is_location_invariant + <__future_base::_Task_setter<_Res_ptr, _Fn, _Res>> + : true_type { }; + #ifndef _GLIBCXX_ASYNC_ABI_COMPAT /// Common implementation for future and shared_future. @@ -994,24 +1003,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Setting the result void set_value(const _Res& __r) - { - auto __setter = _State::__setter(this, __r); - _M_future->_M_set_result(std::move(__setter)); - } + { _M_future->_M_set_result(_State::__setter(this, __r)); } void set_value(_Res&& __r) - { - auto __setter = _State::__setter(this, std::move(__r)); - _M_future->_M_set_result(std::move(__setter)); - } + { _M_future->_M_set_result(_State::__setter(this, std::move(__r))); } void set_exception(exception_ptr __p) - { - auto __setter = _State::__setter(__p, this); - _M_future->_M_set_result(std::move(__setter)); - } + { _M_future->_M_set_result(_State::__setter(__p, this)); } }; template @@ -1092,17 +1092,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Setting the result void set_value(_Res& __r) - { - auto __setter = _State::__setter(this, __r); - _M_future->_M_set_result(std::move(__setter)); - } + { _M_future->_M_set_result(_State::__setter(this, __r)); } void set_exception(exception_ptr __p) - { - auto __setter = _State::__setter(__p, this); - _M_future->_M_set_result(std::move(__setter)); - } + { _M_future->_M_set_result(_State::__setter(__p, this)); } }; /// Explicit specialization for promise @@ -1177,10 +1171,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void set_exception(exception_ptr __p) - { - auto __setter = _State::__setter(__p, this); - _M_future->_M_set_result(std::move(__setter)); - } + { _M_future->_M_set_result(_State::__setter(__p, this)); } }; // set void @@ -1196,28 +1187,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION promise* _M_promise; }; - inline __future_base::_State_base::_Setter - __future_base::_State_base::__setter(promise* __prom) - { - return _Setter{ __prom }; - } - inline void promise::set_value() - { - auto __setter = _State::__setter(this); - _M_future->_M_set_result(std::move(__setter)); - } - + { _M_future->_M_set_result(_State::_Setter{ this }); } - template + template struct __future_base::_Task_setter { _Ptr_type operator()() { __try { - _M_result->_M_set(_M_fn()); + (*_M_result)->_M_set((*_M_fn)()); } __catch(const __cxxabiv1::__forced_unwind&) { @@ -1225,22 +1206,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } __catch(...) { - _M_result->_M_error = current_exception(); + (*_M_result)->_M_error = current_exception(); } - return std::move(_M_result); + return std::move(*_M_result); } - _Ptr_type& _M_result; - std::function<_Res()> _M_fn; + _Ptr_type* _M_result; + _Fn* _M_fn; }; - template - struct __future_base::_Task_setter<_Ptr_type, void> + template + struct __future_base::_Task_setter<_Ptr_type, _Fn, void> { _Ptr_type operator()() { __try { - _M_fn(); + (*_M_fn)(); } __catch(const __cxxabiv1::__forced_unwind&) { @@ -1248,12 +1229,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } __catch(...) { - _M_result->_M_error = current_exception(); + (*_M_result)->_M_error = current_exception(); } - return std::move(_M_result); + return std::move(*_M_result); } - _Ptr_type& _M_result; - std::function _M_fn; + _Ptr_type* _M_result; + _Fn* _M_fn; }; template @@ -1294,8 +1275,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 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 __setter = _S_task_setter(this->_M_result, std::move(__boundfn)); - this->_M_set_result(std::move(__setter)); + this->_M_set_result(_S_task_setter(this->_M_result, __boundfn)); } virtual shared_ptr<_Task_state_base<_Res(_Args...)>>