summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-07 20:13:52 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-07 20:13:52 +0000
commit28b3c9274184802d59d9918e9327df21defa49fb (patch)
treeae33b523c844eedaec0bce42c4bbdd0aa7df280d
parent392214f61bf5995eee9480d8f54cc32093f0aee5 (diff)
downloadgcc-28b3c9274184802d59d9918e9327df21defa49fb.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@213737 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog15
-rw-r--r--libstdc++-v3/include/std/future122
2 files changed, 66 insertions, 71 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 6dfddd052f5..00a76a82a68 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -11,6 +11,21 @@
* testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
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>
PR c++/15339
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index be2ed96f972..c3aaaec22d9 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<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&>
- || is_same<const _Res, _Arg>::value, // promise<R>
+ || is_same<const _Res, _Arg>::value, // promise<R>
"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<typename _Res, typename _Arg>
static _Setter<_Res, _Arg&&>
__setter(promise<_Res>* __prom, _Arg&& __arg)
{
- return _Setter<_Res, _Arg&&>{ __prom, __arg };
+ return _Setter<_Res, _Arg&&>{ __prom, &__arg };
}
template<typename _Res>
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<void, void>
- __setter(promise<void>* __prom);
-
template<typename _Tp>
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<mutex>& __lock)
+ _M_do_set(function<_Ptr_type()>* __f, unique_lock<mutex>* __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<typename _Res_ptr,
+ template<typename _Res_ptr, typename _Fn,
typename _Res = typename _Res_ptr::element_type::result_type>
struct _Task_setter;
template<typename _Res_ptr, typename _BoundFn>
- 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<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
/// 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<typename _Res>
@@ -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<void>
@@ -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<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
promise<void>::set_value()
- {
- auto __setter = _State::__setter(this);
- _M_future->_M_set_result(std::move(__setter));
- }
-
+ { _M_future->_M_set_result(_State::_Setter<void, void>{ this }); }
- template<typename _Ptr_type, typename _Res>
+ template<typename _Ptr_type, typename _Fn, typename _Res>
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<typename _Ptr_type>
- struct __future_base::_Task_setter<_Ptr_type, void>
+ template<typename _Ptr_type, typename _Fn>
+ 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<void()> _M_fn;
+ _Ptr_type* _M_result;
+ _Fn* _M_fn;
};
template<typename _Res, typename... _Args>
@@ -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...)>>