// -*- C++ -*- // Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file include/future * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_FUTURE #define _GLIBCXX_FUTURE 1 #pragma GCC system_header #ifndef __GXX_EXPERIMENTAL_CXX0X__ # include #else #include #include #include #include #include #include #include #include #include namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @defgroup futures Futures * @ingroup concurrency * * Classes for futures support. * @{ */ /// Error code for futures enum class future_errc { future_already_retrieved = 1, promise_already_satisfied, no_state, broken_promise }; /// Specialization. template<> struct is_error_code_enum : public true_type { }; /// Points to a statically-allocated object derived from error_category. const error_category& future_category() noexcept; /// Overload for make_error_code. inline error_code make_error_code(future_errc __errc) noexcept { return error_code(static_cast(__errc), future_category()); } /// Overload for make_error_condition. inline error_condition make_error_condition(future_errc __errc) noexcept { return error_condition(static_cast(__errc), future_category()); } /** * @brief Exception type thrown by futures. * @ingroup exceptions */ class future_error : public logic_error { error_code _M_code; public: explicit future_error(error_code __ec) : logic_error("std::future_error"), _M_code(__ec) { } virtual ~future_error() noexcept; virtual const char* what() const noexcept; const error_code& code() const noexcept { return _M_code; } }; // Forward declarations. template class future; template class shared_future; template class atomic_future; template class packaged_task; template class promise; /// Launch code for futures enum class launch { async = 1, deferred = 2 }; constexpr launch operator&(launch __x, launch __y) { return static_cast( static_cast(__x) & static_cast(__y)); } constexpr launch operator|(launch __x, launch __y) { return static_cast( static_cast(__x) | static_cast(__y)); } constexpr launch operator^(launch __x, launch __y) { return static_cast( static_cast(__x) ^ static_cast(__y)); } constexpr launch operator~(launch __x) { return static_cast(~static_cast(__x)); } inline launch& operator&=(launch& __x, launch __y) { return __x = __x & __y; } inline launch& operator|=(launch& __x, launch __y) { return __x = __x | __y; } inline launch& operator^=(launch& __x, launch __y) { return __x = __x ^ __y; } /// Status code for futures enum class future_status { ready, timeout, deferred }; template future::type> async(launch __policy, _Fn&& __fn, _Args&&... __args); template struct __async_sfinae_helper { typedef future::type> type; }; template struct __async_sfinae_helper { }; template typename __async_sfinae_helper::type, _Fn, _Args...>::type async(_Fn&& __fn, _Args&&... __args); #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \ && (ATOMIC_INT_LOCK_FREE > 1) /// Base class and enclosing scope. struct __future_base { /// Base class for results. struct _Result_base { exception_ptr _M_error; _Result_base(const _Result_base&) = delete; _Result_base& operator=(const _Result_base&) = delete; // _M_destroy() allows derived classes to control deallocation virtual void _M_destroy() = 0; struct _Deleter { void operator()(_Result_base* __fr) const { __fr->_M_destroy(); } }; protected: _Result_base(); virtual ~_Result_base(); }; /// Result. template struct _Result : _Result_base { private: typedef alignment_of<_Res> __a_of; typedef aligned_storage __align_storage; typedef typename __align_storage::type __align_type; __align_type _M_storage; bool _M_initialized; public: _Result() noexcept : _M_initialized() { } ~_Result() { if (_M_initialized) _M_value().~_Res(); } // Return lvalue, future will add const or rvalue-reference _Res& _M_value() noexcept { return *static_cast<_Res*>(_M_addr()); } void _M_set(const _Res& __res) { ::new (_M_addr()) _Res(__res); _M_initialized = true; } void _M_set(_Res&& __res) { ::new (_M_addr()) _Res(std::move(__res)); _M_initialized = true; } private: void _M_destroy() { delete this; } void* _M_addr() noexcept { return static_cast(&_M_storage); } }; /// A unique_ptr based on the instantiating type. template using _Ptr = unique_ptr<_Res, _Result_base::_Deleter>; /// Result_alloc. template struct _Result_alloc final : _Result<_Res>, _Alloc { typedef typename allocator_traits<_Alloc>::template rebind_alloc<_Result_alloc> __allocator_type; explicit _Result_alloc(const _Alloc& __a) : _Result<_Res>(), _Alloc(__a) { } private: void _M_destroy() { typedef allocator_traits<__allocator_type> __traits; __allocator_type __a(*this); __traits::destroy(__a, this); __traits::deallocate(__a, this, 1); } }; template static _Ptr<_Result_alloc<_Res, _Allocator>> _S_allocate_result(const _Allocator& __a) { typedef _Result_alloc<_Res, _Allocator> __result_type; typedef allocator_traits __traits; typename __traits::allocator_type __a2(__a); __result_type* __p = __traits::allocate(__a2, 1); __try { __traits::construct(__a2, __p, __a); } __catch(...) { __traits::deallocate(__a2, __p, 1); __throw_exception_again; } return _Ptr<__result_type>(__p); } /// Base class for state between a promise and one or more /// associated futures. class _State_base { typedef _Ptr<_Result_base> _Ptr_type; _Ptr_type _M_result; mutex _M_mutex; condition_variable _M_cond; atomic_flag _M_retrieved; once_flag _M_once; public: _State_base() noexcept : _M_result(), _M_retrieved(ATOMIC_FLAG_INIT) { } _State_base(const _State_base&) = delete; _State_base& operator=(const _State_base&) = delete; virtual ~_State_base(); _Result_base& wait() { _M_run_deferred(); unique_lock __lock(_M_mutex); _M_cond.wait(__lock, [&] { return _M_ready(); }); return *_M_result; } template future_status wait_for(const chrono::duration<_Rep, _Period>& __rel) { unique_lock __lock(_M_mutex); if (_M_cond.wait_for(__lock, __rel, [&] { return _M_ready(); })) return future_status::ready; return future_status::timeout; } template future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs) { unique_lock __lock(_M_mutex); if (_M_cond.wait_until(__lock, __abs, [&] { return _M_ready(); })) return future_status::ready; return future_status::timeout; } void _M_set_result(function<_Ptr_type()> __res, bool __ignore_failure = false) { bool __set = __ignore_failure; // all calls to this function are serialized, // side-effects of invoking __res only happen once call_once(_M_once, &_State_base::_M_do_set, this, ref(__res), ref(__set)); if (!__set) __throw_future_error(int(future_errc::promise_already_satisfied)); } void _M_break_promise(_Ptr_type __res) { if (static_cast(__res)) { error_code __ec(make_error_code(future_errc::broken_promise)); __res->_M_error = copy_exception(future_error(__ec)); { lock_guard __lock(_M_mutex); _M_result.swap(__res); } _M_cond.notify_all(); } } // Called when this object is passed to a future. void _M_set_retrieved_flag() { if (_M_retrieved.test_and_set()) __throw_future_error(int(future_errc::future_already_retrieved)); } template struct _Setter; // set lvalues template struct _Setter<_Res, _Arg&> { // check this is only used by promise::set_value(const R&) // or promise::set_value(R&) static_assert(is_same<_Res, _Arg&>::value // promise || is_same::value, // promise "Invalid specialisation"); typename promise<_Res>::_Ptr_type operator()() { _State_base::_S_check(_M_promise->_M_future); _M_promise->_M_storage->_M_set(_M_arg); return std::move(_M_promise->_M_storage); } promise<_Res>* _M_promise; _Arg& _M_arg; }; // set rvalues template struct _Setter<_Res, _Res&&> { typename promise<_Res>::_Ptr_type operator()() { _State_base::_S_check(_M_promise->_M_future); _M_promise->_M_storage->_M_set(std::move(_M_arg)); return std::move(_M_promise->_M_storage); } promise<_Res>* _M_promise; _Res& _M_arg; }; struct __exception_ptr_tag { }; // set exceptions template struct _Setter<_Res, __exception_ptr_tag> { typename promise<_Res>::_Ptr_type operator()() { _State_base::_S_check(_M_promise->_M_future); _M_promise->_M_storage->_M_error = _M_ex; return std::move(_M_promise->_M_storage); } promise<_Res>* _M_promise; exception_ptr& _M_ex; }; template static _Setter<_Res, _Arg&&> __setter(promise<_Res>* __prom, _Arg&& __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 }; } static _Setter __setter(promise* __prom); template static bool _S_check(const shared_ptr<_Tp>& __p) { if (!static_cast(__p)) __throw_future_error((int)future_errc::no_state); } private: void _M_do_set(function<_Ptr_type()>& __f, bool& __set) { _Ptr_type __res = __f(); { lock_guard __lock(_M_mutex); _M_result.swap(__res); } _M_cond.notify_all(); __set = true; } bool _M_ready() const noexcept { return static_cast(_M_result); } // Misnamed: waits for completion of async function. virtual void _M_run_deferred() { } }; template class _Deferred_state; class _Async_state_common; template class _Async_state_impl; template class _Task_state; template static std::shared_ptr<_State_base> _S_make_deferred_state(_BoundFn&& __fn); template static std::shared_ptr<_State_base> _S_make_async_state(_BoundFn&& __fn); template struct _Task_setter; template class _Task_setter_helper { typedef typename remove_reference<_BoundFn>::type::result_type __res; public: typedef _Task_setter<_Res_ptr, __res> __type; }; template 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. template struct __future_base::_Result<_Res&> : __future_base::_Result_base { _Result() noexcept : _M_value_ptr() { } void _M_set(_Res& __res) noexcept { _M_value_ptr = &__res; } _Res& _M_get() noexcept { return *_M_value_ptr; } private: _Res* _M_value_ptr; void _M_destroy() { delete this; } }; /// Explicit specialization for void. template<> struct __future_base::_Result : __future_base::_Result_base { private: void _M_destroy() { delete this; } }; /// Common implementation for future and shared_future. template class __basic_future : public __future_base { protected: typedef shared_ptr<_State_base> __state_type; typedef __future_base::_Result<_Res>& __result_type; private: __state_type _M_state; public: // Disable copying. __basic_future(const __basic_future&) = delete; __basic_future& operator=(const __basic_future&) = delete; bool valid() const noexcept { return static_cast(_M_state); } void wait() const { _State_base::_S_check(_M_state); _M_state->wait(); } template future_status wait_for(const chrono::duration<_Rep, _Period>& __rel) const { _State_base::_S_check(_M_state); return _M_state->wait_for(__rel); } template future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const { _State_base::_S_check(_M_state); return _M_state->wait_until(__abs); } protected: /// Wait for the state to be ready and rethrow any stored exception __result_type _M_get_result() { _State_base::_S_check(_M_state); _Result_base& __res = _M_state->wait(); if (!(__res._M_error == 0)) rethrow_exception(__res._M_error); return static_cast<__result_type>(__res); } void _M_swap(__basic_future& __that) noexcept { _M_state.swap(__that._M_state); } // Construction of a future by promise::get_future() explicit __basic_future(const __state_type& __state) : _M_state(__state) { _State_base::_S_check(_M_state); _M_state->_M_set_retrieved_flag(); } // Copy construction from a shared_future explicit __basic_future(const shared_future<_Res>&) noexcept; // Move construction from a shared_future explicit __basic_future(shared_future<_Res>&&) noexcept; // Move construction from a future explicit __basic_future(future<_Res>&&) noexcept; constexpr __basic_future() noexcept : _M_state() { } struct _Reset { explicit _Reset(__basic_future& __fut) noexcept : _M_fut(__fut) { } ~_Reset() { _M_fut._M_state.reset(); } __basic_future& _M_fut; }; }; /// Primary template for future. template class future : public __basic_future<_Res> { friend class promise<_Res>; template friend class packaged_task; template friend future::type> async(launch, _Fn&&, _Args&&...); typedef __basic_future<_Res> _Base_type; typedef typename _Base_type::__state_type __state_type; explicit future(const __state_type& __state) : _Base_type(__state) { } public: constexpr future() noexcept : _Base_type() { } /// Move constructor future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } // Disable copying future(const future&) = delete; future& operator=(const future&) = delete; future& operator=(future&& __fut) noexcept { future(std::move(__fut))._M_swap(*this); return *this; } /// Retrieving the value _Res get() { typename _Base_type::_Reset __reset(*this); return std::move(this->_M_get_result()._M_value()); } shared_future<_Res> share(); }; /// Partial specialization for future template class future<_Res&> : public __basic_future<_Res&> { friend class promise<_Res&>; template friend class packaged_task; template friend future::type> async(launch, _Fn&&, _Args&&...); typedef __basic_future<_Res&> _Base_type; typedef typename _Base_type::__state_type __state_type; explicit future(const __state_type& __state) : _Base_type(__state) { } public: constexpr future() noexcept : _Base_type() { } /// Move constructor future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } // Disable copying future(const future&) = delete; future& operator=(const future&) = delete; future& operator=(future&& __fut) noexcept { future(std::move(__fut))._M_swap(*this); return *this; } /// Retrieving the value _Res& get() { typename _Base_type::_Reset __reset(*this); return this->_M_get_result()._M_get(); } shared_future<_Res&> share(); }; /// Explicit specialization for future template<> class future : public __basic_future { friend class promise; template friend class packaged_task; template friend future::type> async(launch, _Fn&&, _Args&&...); typedef __basic_future _Base_type; typedef typename _Base_type::__state_type __state_type; explicit future(const __state_type& __state) : _Base_type(__state) { } public: constexpr future() noexcept : _Base_type() { } /// Move constructor future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } // Disable copying future(const future&) = delete; future& operator=(const future&) = delete; future& operator=(future&& __fut) noexcept { future(std::move(__fut))._M_swap(*this); return *this; } /// Retrieving the value void get() { typename _Base_type::_Reset __reset(*this); this->_M_get_result(); } shared_future share(); }; /// Primary template for shared_future. template class shared_future : public __basic_future<_Res> { typedef __basic_future<_Res> _Base_type; public: constexpr shared_future() noexcept : _Base_type() { } /// Copy constructor shared_future(const shared_future& __sf) : _Base_type(__sf) { } /// Construct from a future rvalue shared_future(future<_Res>&& __uf) noexcept : _Base_type(std::move(__uf)) { } /// Construct from a shared_future rvalue shared_future(shared_future&& __sf) noexcept : _Base_type(std::move(__sf)) { } shared_future& operator=(const shared_future& __sf) { shared_future(__sf)._M_swap(*this); return *this; } shared_future& operator=(shared_future&& __sf) noexcept { shared_future(std::move(__sf))._M_swap(*this); return *this; } /// Retrieving the value const _Res& get() { typename _Base_type::__result_type __r = this->_M_get_result(); _Res& __rs(__r._M_value()); return __rs; } }; /// Partial specialization for shared_future template class shared_future<_Res&> : public __basic_future<_Res&> { typedef __basic_future<_Res&> _Base_type; public: constexpr shared_future() noexcept : _Base_type() { } /// Copy constructor shared_future(const shared_future& __sf) : _Base_type(__sf) { } /// Construct from a future rvalue shared_future(future<_Res&>&& __uf) noexcept : _Base_type(std::move(__uf)) { } /// Construct from a shared_future rvalue shared_future(shared_future&& __sf) noexcept : _Base_type(std::move(__sf)) { } shared_future& operator=(const shared_future& __sf) { shared_future(__sf)._M_swap(*this); return *this; } shared_future& operator=(shared_future&& __sf) noexcept { shared_future(std::move(__sf))._M_swap(*this); return *this; } /// Retrieving the value _Res& get() { return this->_M_get_result()._M_get(); } }; /// Explicit specialization for shared_future template<> class shared_future : public __basic_future { typedef __basic_future _Base_type; public: constexpr shared_future() noexcept : _Base_type() { } /// Copy constructor shared_future(const shared_future& __sf) : _Base_type(__sf) { } /// Construct from a future rvalue shared_future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } /// Construct from a shared_future rvalue shared_future(shared_future&& __sf) noexcept : _Base_type(std::move(__sf)) { } shared_future& operator=(const shared_future& __sf) { shared_future(__sf)._M_swap(*this); return *this; } shared_future& operator=(shared_future&& __sf) noexcept { shared_future(std::move(__sf))._M_swap(*this); return *this; } // Retrieving the value void get() { this->_M_get_result(); } }; // Now we can define the protected __basic_future constructors. template inline __basic_future<_Res>:: __basic_future(const shared_future<_Res>& __sf) noexcept : _M_state(__sf._M_state) { } template inline __basic_future<_Res>:: __basic_future(shared_future<_Res>&& __sf) noexcept : _M_state(std::move(__sf._M_state)) { } template inline __basic_future<_Res>:: __basic_future(future<_Res>&& __uf) noexcept : _M_state(std::move(__uf._M_state)) { } template inline shared_future<_Res> future<_Res>::share() { return shared_future<_Res>(std::move(*this)); } template inline shared_future<_Res&> future<_Res&>::share() { return shared_future<_Res&>(std::move(*this)); } inline shared_future future::share() { return shared_future(std::move(*this)); } /// Primary template for promise template class promise { typedef __future_base::_State_base _State; typedef __future_base::_Result<_Res> _Res_type; typedef __future_base::_Ptr<_Res_type> _Ptr_type; template friend class _State::_Setter; shared_ptr<_State> _M_future; _Ptr_type _M_storage; public: promise() : _M_future(std::make_shared<_State>()), _M_storage(new _Res_type()) { } promise(promise&& __rhs) noexcept : _M_future(std::move(__rhs._M_future)), _M_storage(std::move(__rhs._M_storage)) { } template promise(allocator_arg_t, const _Allocator& __a) : _M_future(std::allocate_shared<_State>(__a)), _M_storage(__future_base::_S_allocate_result<_Res>(__a)) { } template promise(allocator_arg_t, const _Allocator&, promise&& __rhs) : _M_future(std::move(__rhs._M_future)), _M_storage(std::move(__rhs._M_storage)) { } promise(const promise&) = delete; ~promise() { if (static_cast(_M_future) && !_M_future.unique()) _M_future->_M_break_promise(std::move(_M_storage)); } // Assignment promise& operator=(promise&& __rhs) noexcept { promise(std::move(__rhs)).swap(*this); return *this; } promise& operator=(const promise&) = delete; void swap(promise& __rhs) noexcept { _M_future.swap(__rhs._M_future); _M_storage.swap(__rhs._M_storage); } // Retrieving the result future<_Res> get_future() { return future<_Res>(_M_future); } // Setting the result void set_value(const _Res& __r) { auto __setter = _State::__setter(this, __r); _M_future->_M_set_result(std::move(__setter)); } void set_value(_Res&& __r) { auto __setter = _State::__setter(this, std::move(__r)); _M_future->_M_set_result(std::move(__setter)); } void set_exception(exception_ptr __p) { auto __setter = _State::__setter(__p, this); _M_future->_M_set_result(std::move(__setter)); } }; template inline void swap(promise<_Res>& __x, promise<_Res>& __y) noexcept { __x.swap(__y); } template struct uses_allocator, _Alloc> : public true_type { }; /// Partial specialization for promise template class promise<_Res&> { typedef __future_base::_State_base _State; typedef __future_base::_Result<_Res&> _Res_type; typedef __future_base::_Ptr<_Res_type> _Ptr_type; template friend class _State::_Setter; shared_ptr<_State> _M_future; _Ptr_type _M_storage; public: promise() : _M_future(std::make_shared<_State>()), _M_storage(new _Res_type()) { } promise(promise&& __rhs) noexcept : _M_future(std::move(__rhs._M_future)), _M_storage(std::move(__rhs._M_storage)) { } template promise(allocator_arg_t, const _Allocator& __a) : _M_future(std::allocate_shared<_State>(__a)), _M_storage(__future_base::_S_allocate_result<_Res&>(__a)) { } template promise(allocator_arg_t, const _Allocator&, promise&& __rhs) : _M_future(std::move(__rhs._M_future)), _M_storage(std::move(__rhs._M_storage)) { } promise(const promise&) = delete; ~promise() { if (static_cast(_M_future) && !_M_future.unique()) _M_future->_M_break_promise(std::move(_M_storage)); } // Assignment promise& operator=(promise&& __rhs) noexcept { promise(std::move(__rhs)).swap(*this); return *this; } promise& operator=(const promise&) = delete; void swap(promise& __rhs) noexcept { _M_future.swap(__rhs._M_future); _M_storage.swap(__rhs._M_storage); } // Retrieving the result future<_Res&> get_future() { return future<_Res&>(_M_future); } // Setting the result void set_value(_Res& __r) { auto __setter = _State::__setter(this, __r); _M_future->_M_set_result(std::move(__setter)); } void set_exception(exception_ptr __p) { auto __setter = _State::__setter(__p, this); _M_future->_M_set_result(std::move(__setter)); } }; /// Explicit specialization for promise template<> class promise { typedef __future_base::_State_base _State; typedef __future_base::_Result _Res_type; typedef __future_base::_Ptr<_Res_type> _Ptr_type; template friend class _State::_Setter; shared_ptr<_State> _M_future; _Ptr_type _M_storage; public: promise() : _M_future(std::make_shared<_State>()), _M_storage(new _Res_type()) { } promise(promise&& __rhs) noexcept : _M_future(std::move(__rhs._M_future)), _M_storage(std::move(__rhs._M_storage)) { } template promise(allocator_arg_t, const _Allocator& __a) : _M_future(std::allocate_shared<_State>(__a)), _M_storage(__future_base::_S_allocate_result(__a)) { } template promise(allocator_arg_t, const _Allocator&, promise&& __rhs) : _M_future(std::move(__rhs._M_future)), _M_storage(std::move(__rhs._M_storage)) { } promise(const promise&) = delete; ~promise() { if (static_cast(_M_future) && !_M_future.unique()) _M_future->_M_break_promise(std::move(_M_storage)); } // Assignment promise& operator=(promise&& __rhs) noexcept { promise(std::move(__rhs)).swap(*this); return *this; } promise& operator=(const promise&) = delete; void swap(promise& __rhs) noexcept { _M_future.swap(__rhs._M_future); _M_storage.swap(__rhs._M_storage); } // Retrieving the result future get_future() { return future(_M_future); } // Setting the result void set_value(); void set_exception(exception_ptr __p) { auto __setter = _State::__setter(__p, this); _M_future->_M_set_result(std::move(__setter)); } }; // set void template<> struct __future_base::_State_base::_Setter { promise::_Ptr_type operator()() { _State_base::_S_check(_M_promise->_M_future); return std::move(_M_promise->_M_storage); } 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)); } template struct __future_base::_Task_setter { _Ptr_type operator()() { __try { _M_result->_M_set(_M_fn()); } __catch(...) { _M_result->_M_error = current_exception(); } return std::move(_M_result); } _Ptr_type& _M_result; std::function<_Res()> _M_fn; }; template struct __future_base::_Task_setter<_Ptr_type, void> { _Ptr_type operator()() { __try { _M_fn(); } __catch(...) { _M_result->_M_error = current_exception(); } return std::move(_M_result); } _Ptr_type& _M_result; std::function _M_fn; }; template struct __future_base::_Task_state<_Res(_Args...)> final : __future_base::_State_base { typedef _Res _Res_type; _Task_state(std::function<_Res(_Args...)> __task) : _M_result(new _Result<_Res>()), _M_task(std::move(__task)) { } template _Task_state(_Func&& __task, const _Alloc& __a) : _M_result(_S_allocate_result<_Res>(__a)), _M_task(allocator_arg, __a, std::move(__task)) { } void _M_run(_Args... __args) { // bound arguments decay so wrap lvalue references 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)); } typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; _Ptr_type _M_result; std::function<_Res(_Args...)> _M_task; template static reference_wrapper<_Tp> _S_maybe_wrap_ref(_Tp& __t) { return std::ref(__t); } template static typename enable_if::value, _Tp>::type&& _S_maybe_wrap_ref(_Tp&& __t) { return std::forward<_Tp>(__t); } }; template::type>::value> struct __constrain_pkgdtask { typedef void __type; }; template struct __constrain_pkgdtask<_Task, _Fn, true> { }; /// packaged_task template class packaged_task<_Res(_ArgTypes...)> { typedef __future_base::_Task_state<_Res(_ArgTypes...)> _State_type; shared_ptr<_State_type> _M_state; public: // Construction and destruction packaged_task() noexcept { } template explicit packaged_task(allocator_arg_t, const _Allocator& __a) noexcept { } template::__type> explicit packaged_task(_Fn&& __fn) : _M_state(std::make_shared<_State_type>(std::forward<_Fn>(__fn))) { } template::__type> explicit packaged_task(allocator_arg_t, const _Allocator& __a, _Fn&& __fn) : _M_state(std::allocate_shared<_State_type>(__a, std::forward<_Fn>(__fn))) { } ~packaged_task() { if (static_cast(_M_state) && !_M_state.unique()) _M_state->_M_break_promise(std::move(_M_state->_M_result)); } // No copy packaged_task(const packaged_task&) = delete; packaged_task& operator=(const packaged_task&) = delete; template explicit packaged_task(allocator_arg_t, const _Allocator&, const packaged_task&) = delete; // Move support packaged_task(packaged_task&& __other) noexcept { this->swap(__other); } template explicit packaged_task(allocator_arg_t, const _Allocator&, packaged_task&& __other) noexcept { this->swap(__other); } packaged_task& operator=(packaged_task&& __other) noexcept { packaged_task(std::move(__other)).swap(*this); return *this; } void swap(packaged_task& __other) noexcept { _M_state.swap(__other._M_state); } bool valid() const noexcept { return static_cast(_M_state); } // Result retrieval future<_Res> get_future() { return future<_Res>(_M_state); } // Execution void operator()(_ArgTypes... __args) { __future_base::_State_base::_S_check(_M_state); _M_state->_M_run(std::forward<_ArgTypes>(__args)...); } void reset() { __future_base::_State_base::_S_check(_M_state); packaged_task(std::move(_M_state->_M_task)).swap(*this); } }; /// swap template inline void swap(packaged_task<_Res(_ArgTypes...)>& __x, packaged_task<_Res(_ArgTypes...)>& __y) noexcept { __x.swap(__y); } template struct uses_allocator, _Alloc> : public true_type { }; template class __future_base::_Deferred_state final : public __future_base::_State_base { public: explicit _Deferred_state(_BoundFn&& __fn) : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) { } private: typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; _Ptr_type _M_result; _BoundFn _M_fn; virtual void _M_run_deferred() { // safe to call multiple times so ignore failure _M_set_result(_S_task_setter(_M_result, _M_fn), true); } }; class __future_base::_Async_state_common : public __future_base::_State_base { protected: #ifdef _GLIBCXX_ASYNC_ABI_COMPAT ~_Async_state_common(); #else ~_Async_state_common() = default; #endif // Allow non-timed waiting functions to block until the thread completes, // as if joined. virtual void _M_run_deferred() { _M_join(); } void _M_join() { std::call_once(_M_once, &thread::join, ref(_M_thread)); } thread _M_thread; once_flag _M_once; }; template class __future_base::_Async_state_impl final : public __future_base::_Async_state_common { public: explicit _Async_state_impl(_BoundFn&& __fn) : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) { _M_thread = std::thread{ [this] { _M_set_result(_S_task_setter(_M_result, _M_fn)); } }; } ~_Async_state_impl() { _M_join(); } private: typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; _Ptr_type _M_result; _BoundFn _M_fn; }; template 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 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 future::type> async(launch __policy, _Fn&& __fn, _Args&&... __args) { typedef typename result_of<_Fn(_Args...)>::type result_type; std::shared_ptr<__future_base::_State_base> __state; if ((__policy & (launch::async|launch::deferred)) == launch::async) { __state = __future_base::_S_make_async_state(std::__bind_simple( std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)); } else { __state = __future_base::_S_make_deferred_state(std::__bind_simple( std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)); } return future(__state); } /// async, potential overload template inline typename __async_sfinae_helper::type, _Fn, _Args...>::type async(_Fn&& __fn, _Args&&... __args) { return async(launch::async|launch::deferred, std::forward<_Fn>(__fn), std::forward<_Args>(__args)...); } #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 // && ATOMIC_INT_LOCK_FREE // @} group futures _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif // __GXX_EXPERIMENTAL_CXX0X__ #endif // _GLIBCXX_FUTURE