future (_State_baseV2::_M_set_result): Pass pointers to _M_do_set.

* 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<void>*)): 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.

From-SVN: r213737
This commit is contained in:
Jonathan Wakely 2014-08-07 21:13:52 +01:00 committed by Jonathan Wakely
parent 2d45625fa7
commit 4e48c10968
2 changed files with 66 additions and 71 deletions

View File

@ -11,6 +11,21 @@
* testsuite/23_containers/list/requirements/dr438/insert_neg.cc: * testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
Likewise. Likewise.
* 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<void>*)): 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.
2014-08-02 Paolo Carlini <paolo.carlini@oracle.com> 2014-08-02 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/15339 PR c++/15339

View File

@ -358,7 +358,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// all calls to this function are serialized, // all calls to this function are serialized,
// side-effects of invoking __res only happen once // side-effects of invoking __res only happen once
call_once(_M_once, &_State_baseV2::_M_do_set, this, call_once(_M_once, &_State_baseV2::_M_do_set, this,
ref(__res), ref(__lock)); std::__addressof(__res), std::__addressof(__lock));
if (__lock.owns_lock()) if (__lock.owns_lock())
_M_cond.notify_all(); _M_cond.notify_all();
else if (!__ignore_failure) else if (!__ignore_failure)
@ -396,7 +396,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct _Setter<_Res, _Arg&> struct _Setter<_Res, _Arg&>
{ {
// check this is only used by promise<R>::set_value(const R&) // check this is only used by promise<R>::set_value(const R&)
// or promise<R>::set_value(R&) // or promise<R&>::set_value(R&)
static_assert(is_same<_Res, _Arg&>::value // promise<R&> static_assert(is_same<_Res, _Arg&>::value // promise<R&>
|| is_same<const _Res, _Arg>::value, // promise<R> || is_same<const _Res, _Arg>::value, // promise<R>
"Invalid specialisation"); "Invalid specialisation");
@ -404,11 +404,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename promise<_Res>::_Ptr_type operator()() typename promise<_Res>::_Ptr_type operator()()
{ {
_State_baseV2::_S_check(_M_promise->_M_future); _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); return std::move(_M_promise->_M_storage);
} }
promise<_Res>* _M_promise; promise<_Res>* _M_promise;
_Arg& _M_arg; _Arg* _M_arg;
}; };
// set rvalues // set rvalues
@ -418,11 +418,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename promise<_Res>::_Ptr_type operator()() typename promise<_Res>::_Ptr_type operator()()
{ {
_State_baseV2::_S_check(_M_promise->_M_future); _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); return std::move(_M_promise->_M_storage);
} }
promise<_Res>* _M_promise; promise<_Res>* _M_promise;
_Res& _M_arg; _Res* _M_arg;
}; };
struct __exception_ptr_tag { }; struct __exception_ptr_tag { };
@ -434,31 +434,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename promise<_Res>::_Ptr_type operator()() typename promise<_Res>::_Ptr_type operator()()
{ {
_State_baseV2::_S_check(_M_promise->_M_future); _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); return std::move(_M_promise->_M_storage);
} }
promise<_Res>* _M_promise; promise<_Res>* _M_promise;
exception_ptr& _M_ex; exception_ptr* _M_ex;
}; };
template<typename _Res, typename _Arg> template<typename _Res, typename _Arg>
static _Setter<_Res, _Arg&&> static _Setter<_Res, _Arg&&>
__setter(promise<_Res>* __prom, _Arg&& __arg) __setter(promise<_Res>* __prom, _Arg&& __arg)
{ {
return _Setter<_Res, _Arg&&>{ __prom, __arg }; return _Setter<_Res, _Arg&&>{ __prom, &__arg };
} }
template<typename _Res> template<typename _Res>
static _Setter<_Res, __exception_ptr_tag> static _Setter<_Res, __exception_ptr_tag>
__setter(exception_ptr& __ex, promise<_Res>* __prom) __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<void, void>
__setter(promise<void>* __prom);
template<typename _Tp> template<typename _Tp>
static void static void
_S_check(const shared_ptr<_Tp>& __p) _S_check(const shared_ptr<_Tp>& __p)
@ -469,10 +466,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private: private:
void void
_M_do_set(function<_Ptr_type()>& __f, unique_lock<mutex>& __lock) _M_do_set(function<_Ptr_type()>* __f, unique_lock<mutex>* __lock)
{ {
_Ptr_type __res = __f(); // do not hold lock while running setter _Ptr_type __res = (*__f)(); // do not hold lock while running setter
__lock.lock(); __lock->lock();
_M_result.swap(__res); _M_result.swap(__res);
} }
@ -514,15 +511,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static std::shared_ptr<_State_base> static std::shared_ptr<_State_base>
_S_make_async_state(_BoundFn&& __fn); _S_make_async_state(_BoundFn&& __fn);
template<typename _Res_ptr, template<typename _Res_ptr, typename _Fn,
typename _Res = typename _Res_ptr::element_type::result_type> typename _Res = typename _Res_ptr::element_type::result_type>
struct _Task_setter; struct _Task_setter;
template<typename _Res_ptr, typename _BoundFn> template<typename _Res_ptr, typename _BoundFn>
static _Task_setter<_Res_ptr> static _Task_setter<_Res_ptr, _BoundFn>
_S_task_setter(_Res_ptr& __ptr, _BoundFn&& __call) _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; } void _M_destroy() { delete this; }
}; };
// Allow _Setter objects to be stored locally in std::function
template<typename _Res, typename _Arg>
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<typename _Res_ptr, typename _Fn, typename _Res>
struct __is_location_invariant
<__future_base::_Task_setter<_Res_ptr, _Fn, _Res>>
: true_type { };
#ifndef _GLIBCXX_ASYNC_ABI_COMPAT #ifndef _GLIBCXX_ASYNC_ABI_COMPAT
/// Common implementation for future and shared_future. /// Common implementation for future and shared_future.
@ -994,24 +1003,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Setting the result // Setting the result
void void
set_value(const _Res& __r) set_value(const _Res& __r)
{ { _M_future->_M_set_result(_State::__setter(this, __r)); }
auto __setter = _State::__setter(this, __r);
_M_future->_M_set_result(std::move(__setter));
}
void void
set_value(_Res&& __r) set_value(_Res&& __r)
{ { _M_future->_M_set_result(_State::__setter(this, std::move(__r))); }
auto __setter = _State::__setter(this, std::move(__r));
_M_future->_M_set_result(std::move(__setter));
}
void void
set_exception(exception_ptr __p) set_exception(exception_ptr __p)
{ { _M_future->_M_set_result(_State::__setter(__p, this)); }
auto __setter = _State::__setter(__p, this);
_M_future->_M_set_result(std::move(__setter));
}
}; };
template<typename _Res> template<typename _Res>
@ -1092,17 +1092,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Setting the result // Setting the result
void void
set_value(_Res& __r) set_value(_Res& __r)
{ { _M_future->_M_set_result(_State::__setter(this, __r)); }
auto __setter = _State::__setter(this, __r);
_M_future->_M_set_result(std::move(__setter));
}
void void
set_exception(exception_ptr __p) set_exception(exception_ptr __p)
{ { _M_future->_M_set_result(_State::__setter(__p, this)); }
auto __setter = _State::__setter(__p, this);
_M_future->_M_set_result(std::move(__setter));
}
}; };
/// Explicit specialization for promise<void> /// Explicit specialization for promise<void>
@ -1177,10 +1171,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void void
set_exception(exception_ptr __p) set_exception(exception_ptr __p)
{ { _M_future->_M_set_result(_State::__setter(__p, this)); }
auto __setter = _State::__setter(__p, this);
_M_future->_M_set_result(std::move(__setter));
}
}; };
// set void // set void
@ -1196,28 +1187,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
promise<void>* _M_promise; promise<void>* _M_promise;
}; };
inline __future_base::_State_base::_Setter<void, void>
__future_base::_State_base::__setter(promise<void>* __prom)
{
return _Setter<void, void>{ __prom };
}
inline void inline void
promise<void>::set_value() promise<void>::set_value()
{ { _M_future->_M_set_result(_State::_Setter<void, void>{ this }); }
auto __setter = _State::__setter(this);
_M_future->_M_set_result(std::move(__setter));
}
template<typename _Ptr_type, typename _Fn, typename _Res>
template<typename _Ptr_type, typename _Res>
struct __future_base::_Task_setter struct __future_base::_Task_setter
{ {
_Ptr_type operator()() _Ptr_type operator()()
{ {
__try __try
{ {
_M_result->_M_set(_M_fn()); (*_M_result)->_M_set((*_M_fn)());
} }
__catch(const __cxxabiv1::__forced_unwind&) __catch(const __cxxabiv1::__forced_unwind&)
{ {
@ -1225,22 +1206,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
__catch(...) __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; _Ptr_type* _M_result;
std::function<_Res()> _M_fn; _Fn* _M_fn;
}; };
template<typename _Ptr_type> template<typename _Ptr_type, typename _Fn>
struct __future_base::_Task_setter<_Ptr_type, void> struct __future_base::_Task_setter<_Ptr_type, _Fn, void>
{ {
_Ptr_type operator()() _Ptr_type operator()()
{ {
__try __try
{ {
_M_fn(); (*_M_fn)();
} }
__catch(const __cxxabiv1::__forced_unwind&) __catch(const __cxxabiv1::__forced_unwind&)
{ {
@ -1248,12 +1229,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
__catch(...) __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; _Ptr_type* _M_result;
std::function<void()> _M_fn; _Fn* _M_fn;
}; };
template<typename _Res, typename... _Args> template<typename _Res, typename... _Args>
@ -1294,8 +1275,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// bound arguments decay so wrap lvalue references // bound arguments decay so wrap lvalue references
auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn), auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn),
_S_maybe_wrap_ref(std::forward<_Args>(__args))...); _S_maybe_wrap_ref(std::forward<_Args>(__args))...);
auto __setter = _S_task_setter(this->_M_result, std::move(__boundfn)); this->_M_set_result(_S_task_setter(this->_M_result, __boundfn));
this->_M_set_result(std::move(__setter));
} }
virtual shared_ptr<_Task_state_base<_Res(_Args...)>> virtual shared_ptr<_Task_state_base<_Res(_Args...)>>