diff options
author | Jonathan Wakely <jwakely.gcc@gmail.com> | 2011-07-09 10:13:01 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2011-07-09 11:13:01 +0100 |
commit | 4880236e3fdcec453e6f5f3ac04ea7dae3d31a8c (patch) | |
tree | 220d98d77838ae389eb4bbbfd1acdd2be8814bea /libstdc++-v3/include/std/future | |
parent | 4063e61bc63c3803f8ab2d625ebe8432ac06b3da (diff) | |
download | gcc-4880236e3fdcec453e6f5f3ac04ea7dae3d31a8c.zip gcc-4880236e3fdcec453e6f5f3ac04ea7dae3d31a8c.tar.gz gcc-4880236e3fdcec453e6f5f3ac04ea7dae3d31a8c.tar.bz2 |
re PR libstdc++/49668 ([C++0x] std::thread does not forward its args as rvalues)
2011-07-09 Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/49668
* include/std/functional (__bind_simple): Define.
* include/std/future (_Task_setter): Parameterize by type of result
pointer instead of state object.
(_S_task_setter): Type deduction helper.
(_Task_state): Use _S_task_setter and __bind_simple.
(_Deferred_state, _Async_state): Store call wrapper directly not as
std::function. Use _S_task_setter and __bind_simple.
(_S_make_deferred_state, _S_make_async_state): Type deduction helpers.
(async): Use new functions and __bind_simple.
* include/std/mutex (call_once): Use __bind_simple.
* include/std/thread (thread): Likewise. Remove unused headers.
* src/thread.cc: Add header.
* testsuite/30_threads/async/49668.cc: New.
* testsuite/30_threads/call_once/49668.cc: New.
* testsuite/30_threads/thread/cons/49668.cc: New.
* testsuite/30_threads/thread/cons/moveable.cc: Remove unused bool.
From-SVN: r176073
Diffstat (limited to 'libstdc++-v3/include/std/future')
-rw-r--r-- | libstdc++-v3/include/std/future | 111 |
1 files changed, 72 insertions, 39 deletions
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index 2b3e982..fc2d324 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -488,17 +488,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION virtual void _M_run_deferred() { } }; - template<typename _Res> + template<typename _BoundFn, typename = typename _BoundFn::result_type> class _Deferred_state; - template<typename _Res> + template<typename _BoundFn, typename = typename _BoundFn::result_type> class _Async_state; template<typename _Signature> class _Task_state; - template<typename _StateT, typename _Res = typename _StateT::_Res_type> + 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 _Res> struct _Task_setter; + + template<typename _Res_ptr, typename _BoundFn> + class _Task_setter_helper + { + typedef typename remove_reference<_BoundFn>::type::result_type __res; + public: + typedef _Task_setter<_Res_ptr, __res> __type; + }; + + template<typename _Res_ptr, typename _BoundFn> + static typename _Task_setter_helper<_Res_ptr, _BoundFn>::__type + _S_task_setter(_Res_ptr& __ptr, _BoundFn&& __call) + { + typedef _Task_setter_helper<_Res_ptr, _BoundFn> __helper_type; + typedef typename __helper_type::__type _Setter; + return _Setter{ __ptr, std::ref(__call) }; + } }; /// Partial specialization for reference types. @@ -1165,29 +1190,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } - template<typename _StateT, typename _Res> + template<typename _Ptr_type, typename _Res> struct __future_base::_Task_setter { - typename _StateT::_Ptr_type operator()() + _Ptr_type operator()() { __try { - _M_state->_M_result->_M_set(_M_fn()); + _M_result->_M_set(_M_fn()); } __catch(...) { - _M_state->_M_result->_M_error = current_exception(); + _M_result->_M_error = current_exception(); } - return std::move(_M_state->_M_result); + return std::move(_M_result); } - _StateT* _M_state; + _Ptr_type& _M_result; std::function<_Res()> _M_fn; }; - template<typename _StateT> - struct __future_base::_Task_setter<_StateT, void> + template<typename _Ptr_type> + struct __future_base::_Task_setter<_Ptr_type, void> { - typename _StateT::_Ptr_type operator()() + _Ptr_type operator()() { __try { @@ -1195,11 +1220,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } __catch(...) { - _M_state->_M_result->_M_error = current_exception(); + _M_result->_M_error = current_exception(); } - return std::move(_M_state->_M_result); + return std::move(_M_result); } - _StateT* _M_state; + _Ptr_type& _M_result; std::function<void()> _M_fn; }; @@ -1223,13 +1248,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_run(_Args... __args) { // bound arguments decay so wrap lvalue references - auto __bound = std::bind<_Res>(std::ref(_M_task), - _S_maybe_wrap_ref(std::forward<_Args>(__args))...); - _Task_setter<_Task_state> __setter{ this, std::move(__bound) }; + auto __boundfn = std::__bind_simple(std::ref(_M_task), + _S_maybe_wrap_ref(std::forward<_Args>(__args))...); + auto __setter = _S_task_setter(_M_result, std::move(__boundfn)); _M_set_result(std::move(__setter)); } - template<typename, typename> friend class _Task_setter; typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; _Ptr_type _M_result; std::function<_Res(_Args...)> _M_task; @@ -1331,40 +1355,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public true_type { }; - template<typename _Res> + template<typename _BoundFn, typename _Res> class __future_base::_Deferred_state : public __future_base::_State_base { public: - typedef _Res _Res_type; - explicit - _Deferred_state(std::function<_Res()>&& __fn) + _Deferred_state(_BoundFn&& __fn) : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) { } private: - template<typename, typename> friend class _Task_setter; typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; _Ptr_type _M_result; - std::function<_Res()> _M_fn; + _BoundFn _M_fn; virtual void _M_run_deferred() { - _Task_setter<_Deferred_state> __setter{ this, _M_fn }; // safe to call multiple times so ignore failure - _M_set_result(std::move(__setter), true); + _M_set_result(_S_task_setter(_M_result, _M_fn), true); } }; - template<typename _Res> + template<typename _BoundFn, typename _Res> class __future_base::_Async_state : public __future_base::_State_base { public: - typedef _Res _Res_type; - explicit - _Async_state(std::function<_Res()>&& __fn) + _Async_state(_BoundFn&& __fn) : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)), _M_thread(mem_fn(&_Async_state::_M_do_run), this) { } @@ -1374,17 +1392,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: void _M_do_run() { - _Task_setter<_Async_state> __setter{ this, std::move(_M_fn) }; - _M_set_result(std::move(__setter)); + _M_set_result(_S_task_setter(_M_result, _M_fn)); } - template<typename, typename> friend class _Task_setter; typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; _Ptr_type _M_result; - std::function<_Res()> _M_fn; + _BoundFn _M_fn; thread _M_thread; }; + 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<__fn_type> __state_type; + return std::make_shared<__state_type>(std::move(__fn)); + } + + /// async template<typename _Fn, typename... _Args> future<typename result_of<_Fn(_Args...)>::type> @@ -1394,14 +1429,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::shared_ptr<__future_base::_State_base> __state; if ((__policy & (launch::async|launch::deferred)) == launch::async) { - typedef typename __future_base::_Async_state<result_type> _State; - __state = std::make_shared<_State>(std::bind<result_type>( + __state = __future_base::_S_make_async_state(std::__bind_simple( std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)); } else { - typedef typename __future_base::_Deferred_state<result_type> _State; - __state = std::make_shared<_State>(std::bind<result_type>( + __state = __future_base::_S_make_deferred_state(std::__bind_simple( std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)); } return future<result_type>(__state); |