diff options
author | Andrey Khalyavin <halyavin@gmail.com> | 2022-02-10 16:46:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:30 +0300 |
commit | 4b839d0704ee9be1dabb0310a1f03af24963637b (patch) | |
tree | 1a2c5ffcf89eb53ecd79dbc9bc0a195c27404d0c /contrib/libs/cxxsupp/libcxx/include/future | |
parent | f773626848a7c7456803654292e716b83d69cc12 (diff) | |
download | ydb-4b839d0704ee9be1dabb0310a1f03af24963637b.tar.gz |
Restoring authorship annotation for Andrey Khalyavin <halyavin@gmail.com>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/cxxsupp/libcxx/include/future')
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/include/future | 4882 |
1 files changed, 2441 insertions, 2441 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/include/future b/contrib/libs/cxxsupp/libcxx/include/future index 04ac0c5ca8..89acdba62b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/future +++ b/contrib/libs/cxxsupp/libcxx/include/future @@ -1,2462 +1,2462 @@ -// -*- C++ -*- -//===--------------------------- future -----------------------------------===// -// +// -*- C++ -*- +//===--------------------------- future -----------------------------------===// +// // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP_FUTURE -#define _LIBCPP_FUTURE - -/* - future synopsis - -namespace std -{ - -enum class future_errc -{ - future_already_retrieved = 1, - promise_already_satisfied, - no_state, - broken_promise -}; - -enum class launch -{ - async = 1, - deferred = 2, - any = async | deferred -}; - -enum class future_status -{ - ready, - timeout, - deferred -}; - -template <> struct is_error_code_enum<future_errc> : public true_type { }; -error_code make_error_code(future_errc e) noexcept; -error_condition make_error_condition(future_errc e) noexcept; - -const error_category& future_category() noexcept; - -class future_error - : public logic_error -{ -public: - future_error(error_code ec); // exposition only +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_FUTURE +#define _LIBCPP_FUTURE + +/* + future synopsis + +namespace std +{ + +enum class future_errc +{ + future_already_retrieved = 1, + promise_already_satisfied, + no_state, + broken_promise +}; + +enum class launch +{ + async = 1, + deferred = 2, + any = async | deferred +}; + +enum class future_status +{ + ready, + timeout, + deferred +}; + +template <> struct is_error_code_enum<future_errc> : public true_type { }; +error_code make_error_code(future_errc e) noexcept; +error_condition make_error_condition(future_errc e) noexcept; + +const error_category& future_category() noexcept; + +class future_error + : public logic_error +{ +public: + future_error(error_code ec); // exposition only explicit future_error(future_errc); // C++17 - const error_code& code() const noexcept; - const char* what() const noexcept; -}; - -template <class R> -class promise -{ -public: - promise(); - template <class Allocator> - promise(allocator_arg_t, const Allocator& a); - promise(promise&& rhs) noexcept; - promise(const promise& rhs) = delete; - ~promise(); - - // assignment - promise& operator=(promise&& rhs) noexcept; - promise& operator=(const promise& rhs) = delete; - void swap(promise& other) noexcept; - - // retrieving the result - future<R> get_future(); - - // setting the result - void set_value(const R& r); - void set_value(R&& r); - void set_exception(exception_ptr p); - - // setting the result with deferred notification - void set_value_at_thread_exit(const R& r); - void set_value_at_thread_exit(R&& r); - void set_exception_at_thread_exit(exception_ptr p); -}; - -template <class R> -class promise<R&> -{ -public: - promise(); - template <class Allocator> - promise(allocator_arg_t, const Allocator& a); - promise(promise&& rhs) noexcept; - promise(const promise& rhs) = delete; - ~promise(); - - // assignment - promise& operator=(promise&& rhs) noexcept; - promise& operator=(const promise& rhs) = delete; - void swap(promise& other) noexcept; - - // retrieving the result - future<R&> get_future(); - - // setting the result - void set_value(R& r); - void set_exception(exception_ptr p); - - // setting the result with deferred notification - void set_value_at_thread_exit(R&); - void set_exception_at_thread_exit(exception_ptr p); -}; - -template <> -class promise<void> -{ -public: - promise(); - template <class Allocator> - promise(allocator_arg_t, const Allocator& a); - promise(promise&& rhs) noexcept; - promise(const promise& rhs) = delete; - ~promise(); - - // assignment - promise& operator=(promise&& rhs) noexcept; - promise& operator=(const promise& rhs) = delete; - void swap(promise& other) noexcept; - - // retrieving the result - future<void> get_future(); - - // setting the result - void set_value(); - void set_exception(exception_ptr p); - - // setting the result with deferred notification - void set_value_at_thread_exit(); - void set_exception_at_thread_exit(exception_ptr p); -}; - -template <class R> void swap(promise<R>& x, promise<R>& y) noexcept; - -template <class R, class Alloc> - struct uses_allocator<promise<R>, Alloc> : public true_type {}; - -template <class R> -class future -{ -public: - future() noexcept; - future(future&&) noexcept; - future(const future& rhs) = delete; - ~future(); - future& operator=(const future& rhs) = delete; - future& operator=(future&&) noexcept; - shared_future<R> share() noexcept; - - // retrieving the value - R get(); - - // functions to check state - bool valid() const noexcept; - - void wait() const; - template <class Rep, class Period> - future_status - wait_for(const chrono::duration<Rep, Period>& rel_time) const; - template <class Clock, class Duration> - future_status - wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; -}; - -template <class R> -class future<R&> -{ -public: - future() noexcept; - future(future&&) noexcept; - future(const future& rhs) = delete; - ~future(); - future& operator=(const future& rhs) = delete; - future& operator=(future&&) noexcept; - shared_future<R&> share() noexcept; - - // retrieving the value - R& get(); - - // functions to check state - bool valid() const noexcept; - - void wait() const; - template <class Rep, class Period> - future_status - wait_for(const chrono::duration<Rep, Period>& rel_time) const; - template <class Clock, class Duration> - future_status - wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; -}; - -template <> -class future<void> -{ -public: - future() noexcept; - future(future&&) noexcept; - future(const future& rhs) = delete; - ~future(); - future& operator=(const future& rhs) = delete; - future& operator=(future&&) noexcept; - shared_future<void> share() noexcept; - - // retrieving the value - void get(); - - // functions to check state - bool valid() const noexcept; - - void wait() const; - template <class Rep, class Period> - future_status - wait_for(const chrono::duration<Rep, Period>& rel_time) const; - template <class Clock, class Duration> - future_status - wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; -}; - -template <class R> -class shared_future -{ -public: - shared_future() noexcept; - shared_future(const shared_future& rhs); - shared_future(future<R>&&) noexcept; - shared_future(shared_future&& rhs) noexcept; - ~shared_future(); - shared_future& operator=(const shared_future& rhs); - shared_future& operator=(shared_future&& rhs) noexcept; - - // retrieving the value - const R& get() const; - - // functions to check state - bool valid() const noexcept; - - void wait() const; - template <class Rep, class Period> - future_status - wait_for(const chrono::duration<Rep, Period>& rel_time) const; - template <class Clock, class Duration> - future_status - wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; -}; - -template <class R> -class shared_future<R&> -{ -public: - shared_future() noexcept; - shared_future(const shared_future& rhs); - shared_future(future<R&>&&) noexcept; - shared_future(shared_future&& rhs) noexcept; - ~shared_future(); - shared_future& operator=(const shared_future& rhs); - shared_future& operator=(shared_future&& rhs) noexcept; - - // retrieving the value - R& get() const; - - // functions to check state - bool valid() const noexcept; - - void wait() const; - template <class Rep, class Period> - future_status - wait_for(const chrono::duration<Rep, Period>& rel_time) const; - template <class Clock, class Duration> - future_status - wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; -}; - -template <> -class shared_future<void> -{ -public: - shared_future() noexcept; - shared_future(const shared_future& rhs); - shared_future(future<void>&&) noexcept; - shared_future(shared_future&& rhs) noexcept; - ~shared_future(); - shared_future& operator=(const shared_future& rhs); - shared_future& operator=(shared_future&& rhs) noexcept; - - // retrieving the value - void get() const; - - // functions to check state - bool valid() const noexcept; - - void wait() const; - template <class Rep, class Period> - future_status - wait_for(const chrono::duration<Rep, Period>& rel_time) const; - template <class Clock, class Duration> - future_status - wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; -}; - -template <class F, class... Args> - future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> - async(F&& f, Args&&... args); - -template <class F, class... Args> - future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> - async(launch policy, F&& f, Args&&... args); - -template <class> class packaged_task; // undefined - -template <class R, class... ArgTypes> -class packaged_task<R(ArgTypes...)> -{ -public: - typedef R result_type; // extension - - // construction and destruction - packaged_task() noexcept; - template <class F> - explicit packaged_task(F&& f); - template <class F, class Allocator> - packaged_task(allocator_arg_t, const Allocator& a, F&& f); - ~packaged_task(); - - // no copy - packaged_task(const packaged_task&) = delete; - packaged_task& operator=(const packaged_task&) = delete; - - // move support - packaged_task(packaged_task&& other) noexcept; - packaged_task& operator=(packaged_task&& other) noexcept; - void swap(packaged_task& other) noexcept; - - bool valid() const noexcept; - - // result retrieval - future<R> get_future(); - - // execution - void operator()(ArgTypes... ); - void make_ready_at_thread_exit(ArgTypes...); - - void reset(); -}; - -template <class R> - void swap(packaged_task<R(ArgTypes...)&, packaged_task<R(ArgTypes...)>&) noexcept; - -template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>; - -} // std - -*/ - -#include <__availability> -#include <__config> -#include <__debug> -#include <__memory/allocator_arg_t.h> -#include <__memory/uses_allocator.h> -#include <__utility/decay_copy.h> -#include <__utility/forward.h> -#include <chrono> -#include <exception> -#include <memory> -#include <mutex> -#include <system_error> -#include <thread> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -#pragma GCC system_header -#endif - -#ifdef _LIBCPP_HAS_NO_THREADS -#error <future> is not supported on this single threaded system -#else // !_LIBCPP_HAS_NO_THREADS - -_LIBCPP_BEGIN_NAMESPACE_STD - -//enum class future_errc -_LIBCPP_DECLARE_STRONG_ENUM(future_errc) -{ - future_already_retrieved = 1, - promise_already_satisfied, - no_state, - broken_promise -}; -_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_errc) - -template <> -struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<future_errc> : public true_type {}; - -#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS -template <> -struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<future_errc::__lx> : public true_type { }; -#endif - -//enum class launch -_LIBCPP_DECLARE_STRONG_ENUM(launch) -{ - async = 1, - deferred = 2, - any = async | deferred -}; -_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(launch) - -#ifndef _LIBCPP_HAS_NO_STRONG_ENUMS - -typedef underlying_type<launch>::type __launch_underlying_type; - -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR -launch -operator&(launch __x, launch __y) -{ - return static_cast<launch>(static_cast<__launch_underlying_type>(__x) & - static_cast<__launch_underlying_type>(__y)); -} - -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR -launch -operator|(launch __x, launch __y) -{ - return static_cast<launch>(static_cast<__launch_underlying_type>(__x) | - static_cast<__launch_underlying_type>(__y)); -} - -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR -launch -operator^(launch __x, launch __y) -{ - return static_cast<launch>(static_cast<__launch_underlying_type>(__x) ^ - static_cast<__launch_underlying_type>(__y)); -} - -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR -launch -operator~(launch __x) -{ - return static_cast<launch>(~static_cast<__launch_underlying_type>(__x) & 3); -} - -inline _LIBCPP_INLINE_VISIBILITY -launch& -operator&=(launch& __x, launch __y) -{ - __x = __x & __y; return __x; -} - -inline _LIBCPP_INLINE_VISIBILITY -launch& -operator|=(launch& __x, launch __y) -{ - __x = __x | __y; return __x; -} - -inline _LIBCPP_INLINE_VISIBILITY -launch& -operator^=(launch& __x, launch __y) -{ - __x = __x ^ __y; return __x; -} - -#endif // !_LIBCPP_HAS_NO_STRONG_ENUMS - -//enum class future_status -_LIBCPP_DECLARE_STRONG_ENUM(future_status) -{ - ready, - timeout, - deferred -}; -_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_status) - -_LIBCPP_FUNC_VIS -const error_category& future_category() _NOEXCEPT; - -inline _LIBCPP_INLINE_VISIBILITY -error_code -make_error_code(future_errc __e) _NOEXCEPT -{ - return error_code(static_cast<int>(__e), future_category()); -} - -inline _LIBCPP_INLINE_VISIBILITY -error_condition -make_error_condition(future_errc __e) _NOEXCEPT -{ - return error_condition(static_cast<int>(__e), future_category()); -} - -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_FUTURE_ERROR future_error - : public logic_error -{ - error_code __ec_; -public: - future_error(error_code __ec); - - _LIBCPP_INLINE_VISIBILITY - const error_code& code() const _NOEXCEPT {return __ec_;} - - future_error(const future_error&) _NOEXCEPT = default; - virtual ~future_error() _NOEXCEPT; -}; - -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_NO_EXCEPTIONS -_LIBCPP_AVAILABILITY_FUTURE_ERROR -#endif -void __throw_future_error(future_errc _Ev) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw future_error(make_error_code(_Ev)); -#else - ((void)_Ev); - _VSTD::abort(); -#endif -} - -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state - : public __shared_count -{ -protected: - exception_ptr __exception_; - mutable mutex __mut_; - mutable condition_variable __cv_; - unsigned __state_; - - virtual void __on_zero_shared() _NOEXCEPT; - void __sub_wait(unique_lock<mutex>& __lk); -public: - enum - { - __constructed = 1, - __future_attached = 2, - ready = 4, - deferred = 8 - }; - - _LIBCPP_INLINE_VISIBILITY - __assoc_sub_state() : __state_(0) {} - - _LIBCPP_INLINE_VISIBILITY - bool __has_value() const - {return (__state_ & __constructed) || (__exception_ != nullptr);} - - _LIBCPP_INLINE_VISIBILITY + const error_code& code() const noexcept; + const char* what() const noexcept; +}; + +template <class R> +class promise +{ +public: + promise(); + template <class Allocator> + promise(allocator_arg_t, const Allocator& a); + promise(promise&& rhs) noexcept; + promise(const promise& rhs) = delete; + ~promise(); + + // assignment + promise& operator=(promise&& rhs) noexcept; + promise& operator=(const promise& rhs) = delete; + void swap(promise& other) noexcept; + + // retrieving the result + future<R> get_future(); + + // setting the result + void set_value(const R& r); + void set_value(R&& r); + void set_exception(exception_ptr p); + + // setting the result with deferred notification + void set_value_at_thread_exit(const R& r); + void set_value_at_thread_exit(R&& r); + void set_exception_at_thread_exit(exception_ptr p); +}; + +template <class R> +class promise<R&> +{ +public: + promise(); + template <class Allocator> + promise(allocator_arg_t, const Allocator& a); + promise(promise&& rhs) noexcept; + promise(const promise& rhs) = delete; + ~promise(); + + // assignment + promise& operator=(promise&& rhs) noexcept; + promise& operator=(const promise& rhs) = delete; + void swap(promise& other) noexcept; + + // retrieving the result + future<R&> get_future(); + + // setting the result + void set_value(R& r); + void set_exception(exception_ptr p); + + // setting the result with deferred notification + void set_value_at_thread_exit(R&); + void set_exception_at_thread_exit(exception_ptr p); +}; + +template <> +class promise<void> +{ +public: + promise(); + template <class Allocator> + promise(allocator_arg_t, const Allocator& a); + promise(promise&& rhs) noexcept; + promise(const promise& rhs) = delete; + ~promise(); + + // assignment + promise& operator=(promise&& rhs) noexcept; + promise& operator=(const promise& rhs) = delete; + void swap(promise& other) noexcept; + + // retrieving the result + future<void> get_future(); + + // setting the result + void set_value(); + void set_exception(exception_ptr p); + + // setting the result with deferred notification + void set_value_at_thread_exit(); + void set_exception_at_thread_exit(exception_ptr p); +}; + +template <class R> void swap(promise<R>& x, promise<R>& y) noexcept; + +template <class R, class Alloc> + struct uses_allocator<promise<R>, Alloc> : public true_type {}; + +template <class R> +class future +{ +public: + future() noexcept; + future(future&&) noexcept; + future(const future& rhs) = delete; + ~future(); + future& operator=(const future& rhs) = delete; + future& operator=(future&&) noexcept; + shared_future<R> share() noexcept; + + // retrieving the value + R get(); + + // functions to check state + bool valid() const noexcept; + + void wait() const; + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const; + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; +}; + +template <class R> +class future<R&> +{ +public: + future() noexcept; + future(future&&) noexcept; + future(const future& rhs) = delete; + ~future(); + future& operator=(const future& rhs) = delete; + future& operator=(future&&) noexcept; + shared_future<R&> share() noexcept; + + // retrieving the value + R& get(); + + // functions to check state + bool valid() const noexcept; + + void wait() const; + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const; + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; +}; + +template <> +class future<void> +{ +public: + future() noexcept; + future(future&&) noexcept; + future(const future& rhs) = delete; + ~future(); + future& operator=(const future& rhs) = delete; + future& operator=(future&&) noexcept; + shared_future<void> share() noexcept; + + // retrieving the value + void get(); + + // functions to check state + bool valid() const noexcept; + + void wait() const; + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const; + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; +}; + +template <class R> +class shared_future +{ +public: + shared_future() noexcept; + shared_future(const shared_future& rhs); + shared_future(future<R>&&) noexcept; + shared_future(shared_future&& rhs) noexcept; + ~shared_future(); + shared_future& operator=(const shared_future& rhs); + shared_future& operator=(shared_future&& rhs) noexcept; + + // retrieving the value + const R& get() const; + + // functions to check state + bool valid() const noexcept; + + void wait() const; + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const; + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; +}; + +template <class R> +class shared_future<R&> +{ +public: + shared_future() noexcept; + shared_future(const shared_future& rhs); + shared_future(future<R&>&&) noexcept; + shared_future(shared_future&& rhs) noexcept; + ~shared_future(); + shared_future& operator=(const shared_future& rhs); + shared_future& operator=(shared_future&& rhs) noexcept; + + // retrieving the value + R& get() const; + + // functions to check state + bool valid() const noexcept; + + void wait() const; + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const; + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; +}; + +template <> +class shared_future<void> +{ +public: + shared_future() noexcept; + shared_future(const shared_future& rhs); + shared_future(future<void>&&) noexcept; + shared_future(shared_future&& rhs) noexcept; + ~shared_future(); + shared_future& operator=(const shared_future& rhs); + shared_future& operator=(shared_future&& rhs) noexcept; + + // retrieving the value + void get() const; + + // functions to check state + bool valid() const noexcept; + + void wait() const; + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const; + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; +}; + +template <class F, class... Args> + future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> + async(F&& f, Args&&... args); + +template <class F, class... Args> + future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type> + async(launch policy, F&& f, Args&&... args); + +template <class> class packaged_task; // undefined + +template <class R, class... ArgTypes> +class packaged_task<R(ArgTypes...)> +{ +public: + typedef R result_type; // extension + + // construction and destruction + packaged_task() noexcept; + template <class F> + explicit packaged_task(F&& f); + template <class F, class Allocator> + packaged_task(allocator_arg_t, const Allocator& a, F&& f); + ~packaged_task(); + + // no copy + packaged_task(const packaged_task&) = delete; + packaged_task& operator=(const packaged_task&) = delete; + + // move support + packaged_task(packaged_task&& other) noexcept; + packaged_task& operator=(packaged_task&& other) noexcept; + void swap(packaged_task& other) noexcept; + + bool valid() const noexcept; + + // result retrieval + future<R> get_future(); + + // execution + void operator()(ArgTypes... ); + void make_ready_at_thread_exit(ArgTypes...); + + void reset(); +}; + +template <class R> + void swap(packaged_task<R(ArgTypes...)&, packaged_task<R(ArgTypes...)>&) noexcept; + +template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>; + +} // std + +*/ + +#include <__availability> +#include <__config> +#include <__debug> +#include <__memory/allocator_arg_t.h> +#include <__memory/uses_allocator.h> +#include <__utility/decay_copy.h> +#include <__utility/forward.h> +#include <chrono> +#include <exception> +#include <memory> +#include <mutex> +#include <system_error> +#include <thread> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#ifdef _LIBCPP_HAS_NO_THREADS +#error <future> is not supported on this single threaded system +#else // !_LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +//enum class future_errc +_LIBCPP_DECLARE_STRONG_ENUM(future_errc) +{ + future_already_retrieved = 1, + promise_already_satisfied, + no_state, + broken_promise +}; +_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_errc) + +template <> +struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<future_errc> : public true_type {}; + +#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS +template <> +struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<future_errc::__lx> : public true_type { }; +#endif + +//enum class launch +_LIBCPP_DECLARE_STRONG_ENUM(launch) +{ + async = 1, + deferred = 2, + any = async | deferred +}; +_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(launch) + +#ifndef _LIBCPP_HAS_NO_STRONG_ENUMS + +typedef underlying_type<launch>::type __launch_underlying_type; + +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +launch +operator&(launch __x, launch __y) +{ + return static_cast<launch>(static_cast<__launch_underlying_type>(__x) & + static_cast<__launch_underlying_type>(__y)); +} + +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +launch +operator|(launch __x, launch __y) +{ + return static_cast<launch>(static_cast<__launch_underlying_type>(__x) | + static_cast<__launch_underlying_type>(__y)); +} + +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +launch +operator^(launch __x, launch __y) +{ + return static_cast<launch>(static_cast<__launch_underlying_type>(__x) ^ + static_cast<__launch_underlying_type>(__y)); +} + +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +launch +operator~(launch __x) +{ + return static_cast<launch>(~static_cast<__launch_underlying_type>(__x) & 3); +} + +inline _LIBCPP_INLINE_VISIBILITY +launch& +operator&=(launch& __x, launch __y) +{ + __x = __x & __y; return __x; +} + +inline _LIBCPP_INLINE_VISIBILITY +launch& +operator|=(launch& __x, launch __y) +{ + __x = __x | __y; return __x; +} + +inline _LIBCPP_INLINE_VISIBILITY +launch& +operator^=(launch& __x, launch __y) +{ + __x = __x ^ __y; return __x; +} + +#endif // !_LIBCPP_HAS_NO_STRONG_ENUMS + +//enum class future_status +_LIBCPP_DECLARE_STRONG_ENUM(future_status) +{ + ready, + timeout, + deferred +}; +_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_status) + +_LIBCPP_FUNC_VIS +const error_category& future_category() _NOEXCEPT; + +inline _LIBCPP_INLINE_VISIBILITY +error_code +make_error_code(future_errc __e) _NOEXCEPT +{ + return error_code(static_cast<int>(__e), future_category()); +} + +inline _LIBCPP_INLINE_VISIBILITY +error_condition +make_error_condition(future_errc __e) _NOEXCEPT +{ + return error_condition(static_cast<int>(__e), future_category()); +} + +class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_FUTURE_ERROR future_error + : public logic_error +{ + error_code __ec_; +public: + future_error(error_code __ec); + + _LIBCPP_INLINE_VISIBILITY + const error_code& code() const _NOEXCEPT {return __ec_;} + + future_error(const future_error&) _NOEXCEPT = default; + virtual ~future_error() _NOEXCEPT; +}; + +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +#ifndef _LIBCPP_NO_EXCEPTIONS +_LIBCPP_AVAILABILITY_FUTURE_ERROR +#endif +void __throw_future_error(future_errc _Ev) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw future_error(make_error_code(_Ev)); +#else + ((void)_Ev); + _VSTD::abort(); +#endif +} + +class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state + : public __shared_count +{ +protected: + exception_ptr __exception_; + mutable mutex __mut_; + mutable condition_variable __cv_; + unsigned __state_; + + virtual void __on_zero_shared() _NOEXCEPT; + void __sub_wait(unique_lock<mutex>& __lk); +public: + enum + { + __constructed = 1, + __future_attached = 2, + ready = 4, + deferred = 8 + }; + + _LIBCPP_INLINE_VISIBILITY + __assoc_sub_state() : __state_(0) {} + + _LIBCPP_INLINE_VISIBILITY + bool __has_value() const + {return (__state_ & __constructed) || (__exception_ != nullptr);} + + _LIBCPP_INLINE_VISIBILITY void __attach_future() { - lock_guard<mutex> __lk(__mut_); + lock_guard<mutex> __lk(__mut_); bool __has_future_attached = (__state_ & __future_attached) != 0; if (__has_future_attached) __throw_future_error(future_errc::future_already_retrieved); this->__add_shared(); - __state_ |= __future_attached; - } - - _LIBCPP_INLINE_VISIBILITY - void __set_deferred() {__state_ |= deferred;} - - void __make_ready(); - _LIBCPP_INLINE_VISIBILITY - bool __is_ready() const {return (__state_ & ready) != 0;} - - void set_value(); - void set_value_at_thread_exit(); - - void set_exception(exception_ptr __p); - void set_exception_at_thread_exit(exception_ptr __p); - - void copy(); - - void wait(); - template <class _Rep, class _Period> - future_status - _LIBCPP_INLINE_VISIBILITY - wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const; - template <class _Clock, class _Duration> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - future_status - wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const; - - virtual void __execute(); -}; - -template <class _Clock, class _Duration> -future_status -__assoc_sub_state::wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const -{ - unique_lock<mutex> __lk(__mut_); - if (__state_ & deferred) - return future_status::deferred; - while (!(__state_ & ready) && _Clock::now() < __abs_time) - __cv_.wait_until(__lk, __abs_time); - if (__state_ & ready) - return future_status::ready; - return future_status::timeout; -} - -template <class _Rep, class _Period> -inline -future_status -__assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const -{ - return wait_until(chrono::steady_clock::now() + __rel_time); -} - -template <class _Rp> -class _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_HIDDEN __assoc_state - : public __assoc_sub_state -{ - typedef __assoc_sub_state base; - typedef typename aligned_storage<sizeof(_Rp), alignment_of<_Rp>::value>::type _Up; -protected: - _Up __value_; - - virtual void __on_zero_shared() _NOEXCEPT; -public: - - template <class _Arg> + __state_ |= __future_attached; + } + + _LIBCPP_INLINE_VISIBILITY + void __set_deferred() {__state_ |= deferred;} + + void __make_ready(); + _LIBCPP_INLINE_VISIBILITY + bool __is_ready() const {return (__state_ & ready) != 0;} + + void set_value(); + void set_value_at_thread_exit(); + + void set_exception(exception_ptr __p); + void set_exception_at_thread_exit(exception_ptr __p); + + void copy(); + + void wait(); + template <class _Rep, class _Period> + future_status + _LIBCPP_INLINE_VISIBILITY + wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const; + template <class _Clock, class _Duration> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + future_status + wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const; + + virtual void __execute(); +}; + +template <class _Clock, class _Duration> +future_status +__assoc_sub_state::wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const +{ + unique_lock<mutex> __lk(__mut_); + if (__state_ & deferred) + return future_status::deferred; + while (!(__state_ & ready) && _Clock::now() < __abs_time) + __cv_.wait_until(__lk, __abs_time); + if (__state_ & ready) + return future_status::ready; + return future_status::timeout; +} + +template <class _Rep, class _Period> +inline +future_status +__assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const +{ + return wait_until(chrono::steady_clock::now() + __rel_time); +} + +template <class _Rp> +class _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_HIDDEN __assoc_state + : public __assoc_sub_state +{ + typedef __assoc_sub_state base; + typedef typename aligned_storage<sizeof(_Rp), alignment_of<_Rp>::value>::type _Up; +protected: + _Up __value_; + + virtual void __on_zero_shared() _NOEXCEPT; +public: + + template <class _Arg> void set_value(_Arg&& __arg); - - template <class _Arg> + + template <class _Arg> void set_value_at_thread_exit(_Arg&& __arg); - - _Rp move(); - typename add_lvalue_reference<_Rp>::type copy(); -}; - -template <class _Rp> -void -__assoc_state<_Rp>::__on_zero_shared() _NOEXCEPT -{ - if (this->__state_ & base::__constructed) - reinterpret_cast<_Rp*>(&__value_)->~_Rp(); - delete this; -} - -template <class _Rp> -template <class _Arg> -_LIBCPP_AVAILABILITY_FUTURE -void -__assoc_state<_Rp>::set_value(_Arg&& __arg) -{ - unique_lock<mutex> __lk(this->__mut_); - if (this->__has_value()) - __throw_future_error(future_errc::promise_already_satisfied); - ::new ((void*)&__value_) _Rp(_VSTD::forward<_Arg>(__arg)); - this->__state_ |= base::__constructed | base::ready; - __cv_.notify_all(); -} - -template <class _Rp> -template <class _Arg> -void -__assoc_state<_Rp>::set_value_at_thread_exit(_Arg&& __arg) -{ - unique_lock<mutex> __lk(this->__mut_); - if (this->__has_value()) - __throw_future_error(future_errc::promise_already_satisfied); - ::new ((void*)&__value_) _Rp(_VSTD::forward<_Arg>(__arg)); - this->__state_ |= base::__constructed; - __thread_local_data()->__make_ready_at_thread_exit(this); -} - -template <class _Rp> -_Rp -__assoc_state<_Rp>::move() -{ - unique_lock<mutex> __lk(this->__mut_); - this->__sub_wait(__lk); - if (this->__exception_ != nullptr) - rethrow_exception(this->__exception_); - return _VSTD::move(*reinterpret_cast<_Rp*>(&__value_)); -} - -template <class _Rp> -typename add_lvalue_reference<_Rp>::type -__assoc_state<_Rp>::copy() -{ - unique_lock<mutex> __lk(this->__mut_); - this->__sub_wait(__lk); - if (this->__exception_ != nullptr) - rethrow_exception(this->__exception_); - return *reinterpret_cast<_Rp*>(&__value_); -} - -template <class _Rp> -class _LIBCPP_AVAILABILITY_FUTURE __assoc_state<_Rp&> - : public __assoc_sub_state -{ - typedef __assoc_sub_state base; - typedef _Rp* _Up; -protected: - _Up __value_; - - virtual void __on_zero_shared() _NOEXCEPT; -public: - - void set_value(_Rp& __arg); - void set_value_at_thread_exit(_Rp& __arg); - - _Rp& copy(); -}; - -template <class _Rp> -void -__assoc_state<_Rp&>::__on_zero_shared() _NOEXCEPT -{ - delete this; -} - -template <class _Rp> -void -__assoc_state<_Rp&>::set_value(_Rp& __arg) -{ - unique_lock<mutex> __lk(this->__mut_); - if (this->__has_value()) - __throw_future_error(future_errc::promise_already_satisfied); - __value_ = _VSTD::addressof(__arg); - this->__state_ |= base::__constructed | base::ready; - __cv_.notify_all(); -} - -template <class _Rp> -void -__assoc_state<_Rp&>::set_value_at_thread_exit(_Rp& __arg) -{ - unique_lock<mutex> __lk(this->__mut_); - if (this->__has_value()) - __throw_future_error(future_errc::promise_already_satisfied); - __value_ = _VSTD::addressof(__arg); - this->__state_ |= base::__constructed; - __thread_local_data()->__make_ready_at_thread_exit(this); -} - -template <class _Rp> -_Rp& -__assoc_state<_Rp&>::copy() -{ - unique_lock<mutex> __lk(this->__mut_); - this->__sub_wait(__lk); - if (this->__exception_ != nullptr) - rethrow_exception(this->__exception_); - return *__value_; -} - -template <class _Rp, class _Alloc> -class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc - : public __assoc_state<_Rp> -{ - typedef __assoc_state<_Rp> base; - _Alloc __alloc_; - - virtual void __on_zero_shared() _NOEXCEPT; -public: - _LIBCPP_INLINE_VISIBILITY - explicit __assoc_state_alloc(const _Alloc& __a) - : __alloc_(__a) {} -}; - -template <class _Rp, class _Alloc> -void -__assoc_state_alloc<_Rp, _Alloc>::__on_zero_shared() _NOEXCEPT -{ - if (this->__state_ & base::__constructed) - reinterpret_cast<_Rp*>(_VSTD::addressof(this->__value_))->~_Rp(); - typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _Al; - typedef allocator_traits<_Al> _ATraits; - typedef pointer_traits<typename _ATraits::pointer> _PTraits; - _Al __a(__alloc_); - this->~__assoc_state_alloc(); - __a.deallocate(_PTraits::pointer_to(*this), 1); -} - -template <class _Rp, class _Alloc> -class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc<_Rp&, _Alloc> - : public __assoc_state<_Rp&> -{ - typedef __assoc_state<_Rp&> base; - _Alloc __alloc_; - - virtual void __on_zero_shared() _NOEXCEPT; -public: - _LIBCPP_INLINE_VISIBILITY - explicit __assoc_state_alloc(const _Alloc& __a) - : __alloc_(__a) {} -}; - -template <class _Rp, class _Alloc> -void -__assoc_state_alloc<_Rp&, _Alloc>::__on_zero_shared() _NOEXCEPT -{ - typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _Al; - typedef allocator_traits<_Al> _ATraits; - typedef pointer_traits<typename _ATraits::pointer> _PTraits; - _Al __a(__alloc_); - this->~__assoc_state_alloc(); - __a.deallocate(_PTraits::pointer_to(*this), 1); -} - -template <class _Alloc> -class _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state_alloc - : public __assoc_sub_state -{ - typedef __assoc_sub_state base; - _Alloc __alloc_; - - virtual void __on_zero_shared() _NOEXCEPT; -public: - _LIBCPP_INLINE_VISIBILITY - explicit __assoc_sub_state_alloc(const _Alloc& __a) - : __alloc_(__a) {} -}; - -template <class _Alloc> -void -__assoc_sub_state_alloc<_Alloc>::__on_zero_shared() _NOEXCEPT -{ - typedef typename __allocator_traits_rebind<_Alloc, __assoc_sub_state_alloc>::type _Al; - typedef allocator_traits<_Al> _ATraits; - typedef pointer_traits<typename _ATraits::pointer> _PTraits; - _Al __a(__alloc_); - this->~__assoc_sub_state_alloc(); - __a.deallocate(_PTraits::pointer_to(*this), 1); -} - -template <class _Rp, class _Fp> -class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state - : public __assoc_state<_Rp> -{ - typedef __assoc_state<_Rp> base; - - _Fp __func_; - -public: - _LIBCPP_INLINE_VISIBILITY - explicit __deferred_assoc_state(_Fp&& __f); - - virtual void __execute(); -}; - -template <class _Rp, class _Fp> -inline -__deferred_assoc_state<_Rp, _Fp>::__deferred_assoc_state(_Fp&& __f) - : __func_(_VSTD::forward<_Fp>(__f)) -{ - this->__set_deferred(); -} - -template <class _Rp, class _Fp> -void -__deferred_assoc_state<_Rp, _Fp>::__execute() -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - this->set_value(__func_()); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->set_exception(current_exception()); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template <class _Fp> -class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state<void, _Fp> - : public __assoc_sub_state -{ - typedef __assoc_sub_state base; - - _Fp __func_; - -public: - _LIBCPP_INLINE_VISIBILITY - explicit __deferred_assoc_state(_Fp&& __f); - - virtual void __execute(); -}; - -template <class _Fp> -inline -__deferred_assoc_state<void, _Fp>::__deferred_assoc_state(_Fp&& __f) - : __func_(_VSTD::forward<_Fp>(__f)) -{ - this->__set_deferred(); -} - -template <class _Fp> -void -__deferred_assoc_state<void, _Fp>::__execute() -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - __func_(); - this->set_value(); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->set_exception(current_exception()); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template <class _Rp, class _Fp> -class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state - : public __assoc_state<_Rp> -{ - typedef __assoc_state<_Rp> base; - - _Fp __func_; - - virtual void __on_zero_shared() _NOEXCEPT; -public: - _LIBCPP_INLINE_VISIBILITY - explicit __async_assoc_state(_Fp&& __f); - - virtual void __execute(); -}; - -template <class _Rp, class _Fp> -inline -__async_assoc_state<_Rp, _Fp>::__async_assoc_state(_Fp&& __f) - : __func_(_VSTD::forward<_Fp>(__f)) -{ -} - -template <class _Rp, class _Fp> -void -__async_assoc_state<_Rp, _Fp>::__execute() -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - this->set_value(__func_()); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->set_exception(current_exception()); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template <class _Rp, class _Fp> -void -__async_assoc_state<_Rp, _Fp>::__on_zero_shared() _NOEXCEPT -{ - this->wait(); - base::__on_zero_shared(); -} - -template <class _Fp> -class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state<void, _Fp> - : public __assoc_sub_state -{ - typedef __assoc_sub_state base; - - _Fp __func_; - - virtual void __on_zero_shared() _NOEXCEPT; -public: - _LIBCPP_INLINE_VISIBILITY - explicit __async_assoc_state(_Fp&& __f); - - virtual void __execute(); -}; - -template <class _Fp> -inline -__async_assoc_state<void, _Fp>::__async_assoc_state(_Fp&& __f) - : __func_(_VSTD::forward<_Fp>(__f)) -{ -} - -template <class _Fp> -void -__async_assoc_state<void, _Fp>::__execute() -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - __func_(); - this->set_value(); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->set_exception(current_exception()); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template <class _Fp> -void -__async_assoc_state<void, _Fp>::__on_zero_shared() _NOEXCEPT -{ - this->wait(); - base::__on_zero_shared(); -} - -template <class _Rp> class _LIBCPP_TEMPLATE_VIS promise; -template <class _Rp> class _LIBCPP_TEMPLATE_VIS shared_future; - -// future - -template <class _Rp> class _LIBCPP_TEMPLATE_VIS future; - -template <class _Rp, class _Fp> -_LIBCPP_INLINE_VISIBILITY future<_Rp> -__make_deferred_assoc_state(_Fp&& __f); - -template <class _Rp, class _Fp> -_LIBCPP_INLINE_VISIBILITY future<_Rp> -__make_async_assoc_state(_Fp&& __f); - -template <class _Rp> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future -{ - __assoc_state<_Rp>* __state_; - - explicit future(__assoc_state<_Rp>* __state); - - template <class> friend class promise; - template <class> friend class shared_future; - - template <class _R1, class _Fp> - friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); - template <class _R1, class _Fp> - friend future<_R1> __make_async_assoc_state(_Fp&& __f); - -public: - _LIBCPP_INLINE_VISIBILITY - future() _NOEXCEPT : __state_(nullptr) {} - _LIBCPP_INLINE_VISIBILITY - future(future&& __rhs) _NOEXCEPT - : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} - future(const future&) = delete; - future& operator=(const future&) = delete; - _LIBCPP_INLINE_VISIBILITY - future& operator=(future&& __rhs) _NOEXCEPT - { - future(_VSTD::move(__rhs)).swap(*this); - return *this; - } - - ~future(); - _LIBCPP_INLINE_VISIBILITY - shared_future<_Rp> share() _NOEXCEPT; - - // retrieving the value - _Rp get(); - - _LIBCPP_INLINE_VISIBILITY - void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // functions to check state - _LIBCPP_INLINE_VISIBILITY - bool valid() const _NOEXCEPT {return __state_ != nullptr;} - - _LIBCPP_INLINE_VISIBILITY - void wait() const {__state_->wait();} - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const - {return __state_->wait_for(__rel_time);} - template <class _Clock, class _Duration> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const - {return __state_->wait_until(__abs_time);} -}; - -template <class _Rp> -future<_Rp>::future(__assoc_state<_Rp>* __state) - : __state_(__state) -{ + + _Rp move(); + typename add_lvalue_reference<_Rp>::type copy(); +}; + +template <class _Rp> +void +__assoc_state<_Rp>::__on_zero_shared() _NOEXCEPT +{ + if (this->__state_ & base::__constructed) + reinterpret_cast<_Rp*>(&__value_)->~_Rp(); + delete this; +} + +template <class _Rp> +template <class _Arg> +_LIBCPP_AVAILABILITY_FUTURE +void +__assoc_state<_Rp>::set_value(_Arg&& __arg) +{ + unique_lock<mutex> __lk(this->__mut_); + if (this->__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); + ::new ((void*)&__value_) _Rp(_VSTD::forward<_Arg>(__arg)); + this->__state_ |= base::__constructed | base::ready; + __cv_.notify_all(); +} + +template <class _Rp> +template <class _Arg> +void +__assoc_state<_Rp>::set_value_at_thread_exit(_Arg&& __arg) +{ + unique_lock<mutex> __lk(this->__mut_); + if (this->__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); + ::new ((void*)&__value_) _Rp(_VSTD::forward<_Arg>(__arg)); + this->__state_ |= base::__constructed; + __thread_local_data()->__make_ready_at_thread_exit(this); +} + +template <class _Rp> +_Rp +__assoc_state<_Rp>::move() +{ + unique_lock<mutex> __lk(this->__mut_); + this->__sub_wait(__lk); + if (this->__exception_ != nullptr) + rethrow_exception(this->__exception_); + return _VSTD::move(*reinterpret_cast<_Rp*>(&__value_)); +} + +template <class _Rp> +typename add_lvalue_reference<_Rp>::type +__assoc_state<_Rp>::copy() +{ + unique_lock<mutex> __lk(this->__mut_); + this->__sub_wait(__lk); + if (this->__exception_ != nullptr) + rethrow_exception(this->__exception_); + return *reinterpret_cast<_Rp*>(&__value_); +} + +template <class _Rp> +class _LIBCPP_AVAILABILITY_FUTURE __assoc_state<_Rp&> + : public __assoc_sub_state +{ + typedef __assoc_sub_state base; + typedef _Rp* _Up; +protected: + _Up __value_; + + virtual void __on_zero_shared() _NOEXCEPT; +public: + + void set_value(_Rp& __arg); + void set_value_at_thread_exit(_Rp& __arg); + + _Rp& copy(); +}; + +template <class _Rp> +void +__assoc_state<_Rp&>::__on_zero_shared() _NOEXCEPT +{ + delete this; +} + +template <class _Rp> +void +__assoc_state<_Rp&>::set_value(_Rp& __arg) +{ + unique_lock<mutex> __lk(this->__mut_); + if (this->__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); + __value_ = _VSTD::addressof(__arg); + this->__state_ |= base::__constructed | base::ready; + __cv_.notify_all(); +} + +template <class _Rp> +void +__assoc_state<_Rp&>::set_value_at_thread_exit(_Rp& __arg) +{ + unique_lock<mutex> __lk(this->__mut_); + if (this->__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); + __value_ = _VSTD::addressof(__arg); + this->__state_ |= base::__constructed; + __thread_local_data()->__make_ready_at_thread_exit(this); +} + +template <class _Rp> +_Rp& +__assoc_state<_Rp&>::copy() +{ + unique_lock<mutex> __lk(this->__mut_); + this->__sub_wait(__lk); + if (this->__exception_ != nullptr) + rethrow_exception(this->__exception_); + return *__value_; +} + +template <class _Rp, class _Alloc> +class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc + : public __assoc_state<_Rp> +{ + typedef __assoc_state<_Rp> base; + _Alloc __alloc_; + + virtual void __on_zero_shared() _NOEXCEPT; +public: + _LIBCPP_INLINE_VISIBILITY + explicit __assoc_state_alloc(const _Alloc& __a) + : __alloc_(__a) {} +}; + +template <class _Rp, class _Alloc> +void +__assoc_state_alloc<_Rp, _Alloc>::__on_zero_shared() _NOEXCEPT +{ + if (this->__state_ & base::__constructed) + reinterpret_cast<_Rp*>(_VSTD::addressof(this->__value_))->~_Rp(); + typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _Al; + typedef allocator_traits<_Al> _ATraits; + typedef pointer_traits<typename _ATraits::pointer> _PTraits; + _Al __a(__alloc_); + this->~__assoc_state_alloc(); + __a.deallocate(_PTraits::pointer_to(*this), 1); +} + +template <class _Rp, class _Alloc> +class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc<_Rp&, _Alloc> + : public __assoc_state<_Rp&> +{ + typedef __assoc_state<_Rp&> base; + _Alloc __alloc_; + + virtual void __on_zero_shared() _NOEXCEPT; +public: + _LIBCPP_INLINE_VISIBILITY + explicit __assoc_state_alloc(const _Alloc& __a) + : __alloc_(__a) {} +}; + +template <class _Rp, class _Alloc> +void +__assoc_state_alloc<_Rp&, _Alloc>::__on_zero_shared() _NOEXCEPT +{ + typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _Al; + typedef allocator_traits<_Al> _ATraits; + typedef pointer_traits<typename _ATraits::pointer> _PTraits; + _Al __a(__alloc_); + this->~__assoc_state_alloc(); + __a.deallocate(_PTraits::pointer_to(*this), 1); +} + +template <class _Alloc> +class _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state_alloc + : public __assoc_sub_state +{ + typedef __assoc_sub_state base; + _Alloc __alloc_; + + virtual void __on_zero_shared() _NOEXCEPT; +public: + _LIBCPP_INLINE_VISIBILITY + explicit __assoc_sub_state_alloc(const _Alloc& __a) + : __alloc_(__a) {} +}; + +template <class _Alloc> +void +__assoc_sub_state_alloc<_Alloc>::__on_zero_shared() _NOEXCEPT +{ + typedef typename __allocator_traits_rebind<_Alloc, __assoc_sub_state_alloc>::type _Al; + typedef allocator_traits<_Al> _ATraits; + typedef pointer_traits<typename _ATraits::pointer> _PTraits; + _Al __a(__alloc_); + this->~__assoc_sub_state_alloc(); + __a.deallocate(_PTraits::pointer_to(*this), 1); +} + +template <class _Rp, class _Fp> +class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state + : public __assoc_state<_Rp> +{ + typedef __assoc_state<_Rp> base; + + _Fp __func_; + +public: + _LIBCPP_INLINE_VISIBILITY + explicit __deferred_assoc_state(_Fp&& __f); + + virtual void __execute(); +}; + +template <class _Rp, class _Fp> +inline +__deferred_assoc_state<_Rp, _Fp>::__deferred_assoc_state(_Fp&& __f) + : __func_(_VSTD::forward<_Fp>(__f)) +{ + this->__set_deferred(); +} + +template <class _Rp, class _Fp> +void +__deferred_assoc_state<_Rp, _Fp>::__execute() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + this->set_value(__func_()); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + this->set_exception(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template <class _Fp> +class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state<void, _Fp> + : public __assoc_sub_state +{ + typedef __assoc_sub_state base; + + _Fp __func_; + +public: + _LIBCPP_INLINE_VISIBILITY + explicit __deferred_assoc_state(_Fp&& __f); + + virtual void __execute(); +}; + +template <class _Fp> +inline +__deferred_assoc_state<void, _Fp>::__deferred_assoc_state(_Fp&& __f) + : __func_(_VSTD::forward<_Fp>(__f)) +{ + this->__set_deferred(); +} + +template <class _Fp> +void +__deferred_assoc_state<void, _Fp>::__execute() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + __func_(); + this->set_value(); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + this->set_exception(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template <class _Rp, class _Fp> +class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state + : public __assoc_state<_Rp> +{ + typedef __assoc_state<_Rp> base; + + _Fp __func_; + + virtual void __on_zero_shared() _NOEXCEPT; +public: + _LIBCPP_INLINE_VISIBILITY + explicit __async_assoc_state(_Fp&& __f); + + virtual void __execute(); +}; + +template <class _Rp, class _Fp> +inline +__async_assoc_state<_Rp, _Fp>::__async_assoc_state(_Fp&& __f) + : __func_(_VSTD::forward<_Fp>(__f)) +{ +} + +template <class _Rp, class _Fp> +void +__async_assoc_state<_Rp, _Fp>::__execute() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + this->set_value(__func_()); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + this->set_exception(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template <class _Rp, class _Fp> +void +__async_assoc_state<_Rp, _Fp>::__on_zero_shared() _NOEXCEPT +{ + this->wait(); + base::__on_zero_shared(); +} + +template <class _Fp> +class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state<void, _Fp> + : public __assoc_sub_state +{ + typedef __assoc_sub_state base; + + _Fp __func_; + + virtual void __on_zero_shared() _NOEXCEPT; +public: + _LIBCPP_INLINE_VISIBILITY + explicit __async_assoc_state(_Fp&& __f); + + virtual void __execute(); +}; + +template <class _Fp> +inline +__async_assoc_state<void, _Fp>::__async_assoc_state(_Fp&& __f) + : __func_(_VSTD::forward<_Fp>(__f)) +{ +} + +template <class _Fp> +void +__async_assoc_state<void, _Fp>::__execute() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + __func_(); + this->set_value(); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + this->set_exception(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template <class _Fp> +void +__async_assoc_state<void, _Fp>::__on_zero_shared() _NOEXCEPT +{ + this->wait(); + base::__on_zero_shared(); +} + +template <class _Rp> class _LIBCPP_TEMPLATE_VIS promise; +template <class _Rp> class _LIBCPP_TEMPLATE_VIS shared_future; + +// future + +template <class _Rp> class _LIBCPP_TEMPLATE_VIS future; + +template <class _Rp, class _Fp> +_LIBCPP_INLINE_VISIBILITY future<_Rp> +__make_deferred_assoc_state(_Fp&& __f); + +template <class _Rp, class _Fp> +_LIBCPP_INLINE_VISIBILITY future<_Rp> +__make_async_assoc_state(_Fp&& __f); + +template <class _Rp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future +{ + __assoc_state<_Rp>* __state_; + + explicit future(__assoc_state<_Rp>* __state); + + template <class> friend class promise; + template <class> friend class shared_future; + + template <class _R1, class _Fp> + friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); + template <class _R1, class _Fp> + friend future<_R1> __make_async_assoc_state(_Fp&& __f); + +public: + _LIBCPP_INLINE_VISIBILITY + future() _NOEXCEPT : __state_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY + future(future&& __rhs) _NOEXCEPT + : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} + future(const future&) = delete; + future& operator=(const future&) = delete; + _LIBCPP_INLINE_VISIBILITY + future& operator=(future&& __rhs) _NOEXCEPT + { + future(_VSTD::move(__rhs)).swap(*this); + return *this; + } + + ~future(); + _LIBCPP_INLINE_VISIBILITY + shared_future<_Rp> share() _NOEXCEPT; + + // retrieving the value + _Rp get(); + + _LIBCPP_INLINE_VISIBILITY + void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // functions to check state + _LIBCPP_INLINE_VISIBILITY + bool valid() const _NOEXCEPT {return __state_ != nullptr;} + + _LIBCPP_INLINE_VISIBILITY + void wait() const {__state_->wait();} + template <class _Rep, class _Period> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const + {return __state_->wait_for(__rel_time);} + template <class _Clock, class _Duration> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const + {return __state_->wait_until(__abs_time);} +}; + +template <class _Rp> +future<_Rp>::future(__assoc_state<_Rp>* __state) + : __state_(__state) +{ __state_->__attach_future(); -} - -struct __release_shared_count -{ - void operator()(__shared_count* p) {p->__release_shared();} -}; - -template <class _Rp> -future<_Rp>::~future() -{ - if (__state_) - __state_->__release_shared(); -} - -template <class _Rp> -_Rp -future<_Rp>::get() -{ - unique_ptr<__shared_count, __release_shared_count> __(__state_); - __assoc_state<_Rp>* __s = __state_; - __state_ = nullptr; - return __s->move(); -} - -template <class _Rp> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future<_Rp&> -{ - __assoc_state<_Rp&>* __state_; - - explicit future(__assoc_state<_Rp&>* __state); - - template <class> friend class promise; - template <class> friend class shared_future; - - template <class _R1, class _Fp> - friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); - template <class _R1, class _Fp> - friend future<_R1> __make_async_assoc_state(_Fp&& __f); - -public: - _LIBCPP_INLINE_VISIBILITY - future() _NOEXCEPT : __state_(nullptr) {} - _LIBCPP_INLINE_VISIBILITY - future(future&& __rhs) _NOEXCEPT - : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} - future(const future&) = delete; - future& operator=(const future&) = delete; - _LIBCPP_INLINE_VISIBILITY - future& operator=(future&& __rhs) _NOEXCEPT - { - future(_VSTD::move(__rhs)).swap(*this); - return *this; - } - - ~future(); - _LIBCPP_INLINE_VISIBILITY - shared_future<_Rp&> share() _NOEXCEPT; - - // retrieving the value - _Rp& get(); - - _LIBCPP_INLINE_VISIBILITY - void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // functions to check state - _LIBCPP_INLINE_VISIBILITY - bool valid() const _NOEXCEPT {return __state_ != nullptr;} - - _LIBCPP_INLINE_VISIBILITY - void wait() const {__state_->wait();} - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const - {return __state_->wait_for(__rel_time);} - template <class _Clock, class _Duration> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const - {return __state_->wait_until(__abs_time);} -}; - -template <class _Rp> -future<_Rp&>::future(__assoc_state<_Rp&>* __state) - : __state_(__state) -{ +} + +struct __release_shared_count +{ + void operator()(__shared_count* p) {p->__release_shared();} +}; + +template <class _Rp> +future<_Rp>::~future() +{ + if (__state_) + __state_->__release_shared(); +} + +template <class _Rp> +_Rp +future<_Rp>::get() +{ + unique_ptr<__shared_count, __release_shared_count> __(__state_); + __assoc_state<_Rp>* __s = __state_; + __state_ = nullptr; + return __s->move(); +} + +template <class _Rp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future<_Rp&> +{ + __assoc_state<_Rp&>* __state_; + + explicit future(__assoc_state<_Rp&>* __state); + + template <class> friend class promise; + template <class> friend class shared_future; + + template <class _R1, class _Fp> + friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); + template <class _R1, class _Fp> + friend future<_R1> __make_async_assoc_state(_Fp&& __f); + +public: + _LIBCPP_INLINE_VISIBILITY + future() _NOEXCEPT : __state_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY + future(future&& __rhs) _NOEXCEPT + : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} + future(const future&) = delete; + future& operator=(const future&) = delete; + _LIBCPP_INLINE_VISIBILITY + future& operator=(future&& __rhs) _NOEXCEPT + { + future(_VSTD::move(__rhs)).swap(*this); + return *this; + } + + ~future(); + _LIBCPP_INLINE_VISIBILITY + shared_future<_Rp&> share() _NOEXCEPT; + + // retrieving the value + _Rp& get(); + + _LIBCPP_INLINE_VISIBILITY + void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // functions to check state + _LIBCPP_INLINE_VISIBILITY + bool valid() const _NOEXCEPT {return __state_ != nullptr;} + + _LIBCPP_INLINE_VISIBILITY + void wait() const {__state_->wait();} + template <class _Rep, class _Period> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const + {return __state_->wait_for(__rel_time);} + template <class _Clock, class _Duration> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const + {return __state_->wait_until(__abs_time);} +}; + +template <class _Rp> +future<_Rp&>::future(__assoc_state<_Rp&>* __state) + : __state_(__state) +{ __state_->__attach_future(); -} - -template <class _Rp> -future<_Rp&>::~future() -{ - if (__state_) - __state_->__release_shared(); -} - -template <class _Rp> -_Rp& -future<_Rp&>::get() -{ - unique_ptr<__shared_count, __release_shared_count> __(__state_); - __assoc_state<_Rp&>* __s = __state_; - __state_ = nullptr; - return __s->copy(); -} - -template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE future<void> -{ - __assoc_sub_state* __state_; - - explicit future(__assoc_sub_state* __state); - - template <class> friend class promise; - template <class> friend class shared_future; - - template <class _R1, class _Fp> - friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); - template <class _R1, class _Fp> - friend future<_R1> __make_async_assoc_state(_Fp&& __f); - -public: - _LIBCPP_INLINE_VISIBILITY - future() _NOEXCEPT : __state_(nullptr) {} - _LIBCPP_INLINE_VISIBILITY - future(future&& __rhs) _NOEXCEPT - : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} - future(const future&) = delete; - future& operator=(const future&) = delete; - _LIBCPP_INLINE_VISIBILITY - future& operator=(future&& __rhs) _NOEXCEPT - { - future(_VSTD::move(__rhs)).swap(*this); - return *this; - } - - ~future(); - _LIBCPP_INLINE_VISIBILITY - shared_future<void> share() _NOEXCEPT; - - // retrieving the value - void get(); - - _LIBCPP_INLINE_VISIBILITY - void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // functions to check state - _LIBCPP_INLINE_VISIBILITY - bool valid() const _NOEXCEPT {return __state_ != nullptr;} - - _LIBCPP_INLINE_VISIBILITY - void wait() const {__state_->wait();} - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const - {return __state_->wait_for(__rel_time);} - template <class _Clock, class _Duration> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const - {return __state_->wait_until(__abs_time);} -}; - -template <class _Rp> -inline _LIBCPP_INLINE_VISIBILITY -void -swap(future<_Rp>& __x, future<_Rp>& __y) _NOEXCEPT -{ - __x.swap(__y); -} - -// promise<R> - -template <class _Callable> class packaged_task; - -template <class _Rp> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise -{ - __assoc_state<_Rp>* __state_; - - _LIBCPP_INLINE_VISIBILITY - explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} - - template <class> friend class packaged_task; -public: - promise(); - template <class _Alloc> - promise(allocator_arg_t, const _Alloc& __a); - _LIBCPP_INLINE_VISIBILITY - promise(promise&& __rhs) _NOEXCEPT - : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} - promise(const promise& __rhs) = delete; - ~promise(); - - // assignment - _LIBCPP_INLINE_VISIBILITY - promise& operator=(promise&& __rhs) _NOEXCEPT - { - promise(_VSTD::move(__rhs)).swap(*this); - return *this; - } - promise& operator=(const promise& __rhs) = delete; - - _LIBCPP_INLINE_VISIBILITY - void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // retrieving the result - future<_Rp> get_future(); - - // setting the result - void set_value(const _Rp& __r); - void set_value(_Rp&& __r); - void set_exception(exception_ptr __p); - - // setting the result with deferred notification - void set_value_at_thread_exit(const _Rp& __r); - void set_value_at_thread_exit(_Rp&& __r); - void set_exception_at_thread_exit(exception_ptr __p); -}; - -template <class _Rp> -promise<_Rp>::promise() - : __state_(new __assoc_state<_Rp>) -{ -} - -template <class _Rp> -template <class _Alloc> -promise<_Rp>::promise(allocator_arg_t, const _Alloc& __a0) -{ - typedef __assoc_state_alloc<_Rp, _Alloc> _State; - typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; - typedef __allocator_destructor<_A2> _D2; - _A2 __a(__a0); - unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); - ::new ((void*)_VSTD::addressof(*__hold.get())) _State(__a0); - __state_ = _VSTD::addressof(*__hold.release()); -} - -template <class _Rp> -promise<_Rp>::~promise() -{ - if (__state_) - { - if (!__state_->__has_value() && __state_->use_count() > 1) - __state_->set_exception(make_exception_ptr( - future_error(make_error_code(future_errc::broken_promise)) - )); - __state_->__release_shared(); - } -} - -template <class _Rp> -future<_Rp> -promise<_Rp>::get_future() -{ - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - return future<_Rp>(__state_); -} - -template <class _Rp> -void -promise<_Rp>::set_value(const _Rp& __r) -{ - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_value(__r); -} - -template <class _Rp> -void -promise<_Rp>::set_value(_Rp&& __r) -{ - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_value(_VSTD::move(__r)); -} - -template <class _Rp> -void -promise<_Rp>::set_exception(exception_ptr __p) -{ - _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception: received nullptr" ); - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_exception(__p); -} - -template <class _Rp> -void -promise<_Rp>::set_value_at_thread_exit(const _Rp& __r) -{ - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_value_at_thread_exit(__r); -} - -template <class _Rp> -void -promise<_Rp>::set_value_at_thread_exit(_Rp&& __r) -{ - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_value_at_thread_exit(_VSTD::move(__r)); -} - -template <class _Rp> -void -promise<_Rp>::set_exception_at_thread_exit(exception_ptr __p) -{ - _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_exception_at_thread_exit(__p); -} - -// promise<R&> - -template <class _Rp> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<_Rp&> -{ - __assoc_state<_Rp&>* __state_; - - _LIBCPP_INLINE_VISIBILITY - explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} - - template <class> friend class packaged_task; - -public: - promise(); - template <class _Allocator> - promise(allocator_arg_t, const _Allocator& __a); - _LIBCPP_INLINE_VISIBILITY - promise(promise&& __rhs) _NOEXCEPT - : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} - promise(const promise& __rhs) = delete; - ~promise(); - - // assignment - _LIBCPP_INLINE_VISIBILITY - promise& operator=(promise&& __rhs) _NOEXCEPT - { - promise(_VSTD::move(__rhs)).swap(*this); - return *this; - } - promise& operator=(const promise& __rhs) = delete; - - _LIBCPP_INLINE_VISIBILITY - void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // retrieving the result - future<_Rp&> get_future(); - - // setting the result - void set_value(_Rp& __r); - void set_exception(exception_ptr __p); - - // setting the result with deferred notification - void set_value_at_thread_exit(_Rp&); - void set_exception_at_thread_exit(exception_ptr __p); -}; - -template <class _Rp> -promise<_Rp&>::promise() - : __state_(new __assoc_state<_Rp&>) -{ -} - -template <class _Rp> -template <class _Alloc> -promise<_Rp&>::promise(allocator_arg_t, const _Alloc& __a0) -{ - typedef __assoc_state_alloc<_Rp&, _Alloc> _State; - typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; - typedef __allocator_destructor<_A2> _D2; - _A2 __a(__a0); - unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); - ::new ((void*)_VSTD::addressof(*__hold.get())) _State(__a0); - __state_ = _VSTD::addressof(*__hold.release()); -} - -template <class _Rp> -promise<_Rp&>::~promise() -{ - if (__state_) - { - if (!__state_->__has_value() && __state_->use_count() > 1) - __state_->set_exception(make_exception_ptr( - future_error(make_error_code(future_errc::broken_promise)) - )); - __state_->__release_shared(); - } -} - -template <class _Rp> -future<_Rp&> -promise<_Rp&>::get_future() -{ - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - return future<_Rp&>(__state_); -} - -template <class _Rp> -void -promise<_Rp&>::set_value(_Rp& __r) -{ - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_value(__r); -} - -template <class _Rp> -void -promise<_Rp&>::set_exception(exception_ptr __p) -{ - _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception: received nullptr" ); - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_exception(__p); -} - -template <class _Rp> -void -promise<_Rp&>::set_value_at_thread_exit(_Rp& __r) -{ - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_value_at_thread_exit(__r); -} - -template <class _Rp> -void -promise<_Rp&>::set_exception_at_thread_exit(exception_ptr __p) -{ - _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); - if (__state_ == nullptr) - __throw_future_error(future_errc::no_state); - __state_->set_exception_at_thread_exit(__p); -} - -// promise<void> - -template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<void> -{ - __assoc_sub_state* __state_; - - _LIBCPP_INLINE_VISIBILITY - explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} - - template <class> friend class packaged_task; - -public: - promise(); - template <class _Allocator> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - promise(allocator_arg_t, const _Allocator& __a); - _LIBCPP_INLINE_VISIBILITY - promise(promise&& __rhs) _NOEXCEPT - : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} - promise(const promise& __rhs) = delete; - ~promise(); - - // assignment - _LIBCPP_INLINE_VISIBILITY - promise& operator=(promise&& __rhs) _NOEXCEPT - { - promise(_VSTD::move(__rhs)).swap(*this); - return *this; - } - promise& operator=(const promise& __rhs) = delete; - - _LIBCPP_INLINE_VISIBILITY - void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // retrieving the result - future<void> get_future(); - - // setting the result - void set_value(); - void set_exception(exception_ptr __p); - - // setting the result with deferred notification - void set_value_at_thread_exit(); - void set_exception_at_thread_exit(exception_ptr __p); -}; - -template <class _Alloc> -promise<void>::promise(allocator_arg_t, const _Alloc& __a0) -{ - typedef __assoc_sub_state_alloc<_Alloc> _State; - typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; - typedef __allocator_destructor<_A2> _D2; - _A2 __a(__a0); - unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); - ::new ((void*)_VSTD::addressof(*__hold.get())) _State(__a0); - __state_ = _VSTD::addressof(*__hold.release()); -} - -template <class _Rp> -inline _LIBCPP_INLINE_VISIBILITY -void -swap(promise<_Rp>& __x, promise<_Rp>& __y) _NOEXCEPT -{ - __x.swap(__y); -} - -template <class _Rp, class _Alloc> - struct _LIBCPP_TEMPLATE_VIS uses_allocator<promise<_Rp>, _Alloc> - : public true_type {}; - -// packaged_task - -template<class _Fp> class __packaged_task_base; - -template<class _Rp, class ..._ArgTypes> -class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_base<_Rp(_ArgTypes...)> -{ - __packaged_task_base(const __packaged_task_base&); - __packaged_task_base& operator=(const __packaged_task_base&); -public: - _LIBCPP_INLINE_VISIBILITY - __packaged_task_base() {} - _LIBCPP_INLINE_VISIBILITY - virtual ~__packaged_task_base() {} - virtual void __move_to(__packaged_task_base*) _NOEXCEPT = 0; - virtual void destroy() = 0; - virtual void destroy_deallocate() = 0; - virtual _Rp operator()(_ArgTypes&& ...) = 0; -}; - -template<class _FD, class _Alloc, class _FB> class __packaged_task_func; - -template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> -class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)> - : public __packaged_task_base<_Rp(_ArgTypes...)> -{ - __compressed_pair<_Fp, _Alloc> __f_; -public: - _LIBCPP_INLINE_VISIBILITY - explicit __packaged_task_func(const _Fp& __f) : __f_(__f, __default_init_tag()) {} - _LIBCPP_INLINE_VISIBILITY - explicit __packaged_task_func(_Fp&& __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} - _LIBCPP_INLINE_VISIBILITY - __packaged_task_func(const _Fp& __f, const _Alloc& __a) - : __f_(__f, __a) {} - _LIBCPP_INLINE_VISIBILITY - __packaged_task_func(_Fp&& __f, const _Alloc& __a) - : __f_(_VSTD::move(__f), __a) {} - virtual void __move_to(__packaged_task_base<_Rp(_ArgTypes...)>*) _NOEXCEPT; - virtual void destroy(); - virtual void destroy_deallocate(); - virtual _Rp operator()(_ArgTypes&& ... __args); -}; - -template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> -void -__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__move_to( - __packaged_task_base<_Rp(_ArgTypes...)>* __p) _NOEXCEPT -{ - ::new ((void*)__p) __packaged_task_func(_VSTD::move(__f_.first()), _VSTD::move(__f_.second())); -} - -template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> -void -__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() -{ - __f_.~__compressed_pair<_Fp, _Alloc>(); -} - -template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> -void -__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() -{ - typedef typename __allocator_traits_rebind<_Alloc, __packaged_task_func>::type _Ap; - typedef allocator_traits<_Ap> _ATraits; - typedef pointer_traits<typename _ATraits::pointer> _PTraits; - _Ap __a(__f_.second()); - __f_.~__compressed_pair<_Fp, _Alloc>(); - __a.deallocate(_PTraits::pointer_to(*this), 1); -} - -template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> -_Rp -__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) -{ - return _VSTD::__invoke(__f_.first(), _VSTD::forward<_ArgTypes>(__arg)...); -} - -template <class _Callable> class __packaged_task_function; - -template<class _Rp, class ..._ArgTypes> -class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_function<_Rp(_ArgTypes...)> -{ - typedef __packaged_task_base<_Rp(_ArgTypes...)> __base; - - _LIBCPP_INLINE_VISIBILITY _LIBCPP_NO_CFI - __base* __get_buf() { return (__base*)&__buf_; } - - typename aligned_storage<3*sizeof(void*)>::type __buf_; - __base* __f_; - -public: - typedef _Rp result_type; - - // construct/copy/destroy: - _LIBCPP_INLINE_VISIBILITY - __packaged_task_function() _NOEXCEPT : __f_(nullptr) {} - template<class _Fp> - __packaged_task_function(_Fp&& __f); - template<class _Fp, class _Alloc> - __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f); - - __packaged_task_function(__packaged_task_function&&) _NOEXCEPT; - __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT; - - __packaged_task_function(const __packaged_task_function&) = delete; - __packaged_task_function& operator=(const __packaged_task_function&) = delete; - - ~__packaged_task_function(); - - void swap(__packaged_task_function&) _NOEXCEPT; - - _LIBCPP_INLINE_VISIBILITY - _Rp operator()(_ArgTypes...) const; -}; - -template<class _Rp, class ..._ArgTypes> -__packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(__packaged_task_function&& __f) _NOEXCEPT -{ - if (__f.__f_ == nullptr) - __f_ = nullptr; - else if (__f.__f_ == __f.__get_buf()) - { - __f.__f_->__move_to(__get_buf()); - __f_ = (__base*)&__buf_; - } - else - { - __f_ = __f.__f_; - __f.__f_ = nullptr; - } -} - -template<class _Rp, class ..._ArgTypes> -template <class _Fp> -__packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f) - : __f_(nullptr) -{ - typedef typename remove_reference<typename decay<_Fp>::type>::type _FR; - typedef __packaged_task_func<_FR, allocator<_FR>, _Rp(_ArgTypes...)> _FF; - if (sizeof(_FF) <= sizeof(__buf_)) - { - ::new ((void*)&__buf_) _FF(_VSTD::forward<_Fp>(__f)); - __f_ = (__base*)&__buf_; - } - else - { - typedef allocator<_FF> _Ap; - _Ap __a; - typedef __allocator_destructor<_Ap> _Dp; - unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new ((void*)__hold.get()) _FF(_VSTD::forward<_Fp>(__f), allocator<_FR>(__a)); - __f_ = __hold.release(); - } -} - -template<class _Rp, class ..._ArgTypes> -template <class _Fp, class _Alloc> -__packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function( - allocator_arg_t, const _Alloc& __a0, _Fp&& __f) - : __f_(nullptr) -{ - typedef typename remove_reference<typename decay<_Fp>::type>::type _FR; - typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF; - if (sizeof(_FF) <= sizeof(__buf_)) - { - __f_ = (__base*)&__buf_; - ::new ((void*)__f_) _FF(_VSTD::forward<_Fp>(__f)); - } - else - { - typedef typename __allocator_traits_rebind<_Alloc, _FF>::type _Ap; - _Ap __a(__a0); - typedef __allocator_destructor<_Ap> _Dp; - unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new ((void*)_VSTD::addressof(*__hold.get())) - _FF(_VSTD::forward<_Fp>(__f), _Alloc(__a)); - __f_ = _VSTD::addressof(*__hold.release()); - } -} - -template<class _Rp, class ..._ArgTypes> -__packaged_task_function<_Rp(_ArgTypes...)>& -__packaged_task_function<_Rp(_ArgTypes...)>::operator=(__packaged_task_function&& __f) _NOEXCEPT -{ - if (__f_ == __get_buf()) - __f_->destroy(); - else if (__f_) - __f_->destroy_deallocate(); - __f_ = nullptr; - if (__f.__f_ == nullptr) - __f_ = nullptr; - else if (__f.__f_ == __f.__get_buf()) - { - __f.__f_->__move_to(__get_buf()); - __f_ = __get_buf(); - } - else - { - __f_ = __f.__f_; - __f.__f_ = nullptr; - } - return *this; -} - -template<class _Rp, class ..._ArgTypes> -__packaged_task_function<_Rp(_ArgTypes...)>::~__packaged_task_function() -{ - if (__f_ == __get_buf()) - __f_->destroy(); - else if (__f_) - __f_->destroy_deallocate(); -} - -template<class _Rp, class ..._ArgTypes> -_LIBCPP_NO_CFI -void -__packaged_task_function<_Rp(_ArgTypes...)>::swap(__packaged_task_function& __f) _NOEXCEPT -{ - if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) - { - typename aligned_storage<sizeof(__buf_)>::type __tempbuf; - __base* __t = (__base*)&__tempbuf; - __f_->__move_to(__t); - __f_->destroy(); - __f_ = nullptr; - __f.__f_->__move_to((__base*)&__buf_); - __f.__f_->destroy(); - __f.__f_ = nullptr; - __f_ = (__base*)&__buf_; - __t->__move_to((__base*)&__f.__buf_); - __t->destroy(); - __f.__f_ = (__base*)&__f.__buf_; - } - else if (__f_ == (__base*)&__buf_) - { - __f_->__move_to((__base*)&__f.__buf_); - __f_->destroy(); - __f_ = __f.__f_; - __f.__f_ = (__base*)&__f.__buf_; - } - else if (__f.__f_ == (__base*)&__f.__buf_) - { - __f.__f_->__move_to((__base*)&__buf_); - __f.__f_->destroy(); - __f.__f_ = __f_; - __f_ = (__base*)&__buf_; - } - else - _VSTD::swap(__f_, __f.__f_); -} - -template<class _Rp, class ..._ArgTypes> -inline -_Rp -__packaged_task_function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const -{ - return (*__f_)(_VSTD::forward<_ArgTypes>(__arg)...); -} - -template<class _Rp, class ..._ArgTypes> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<_Rp(_ArgTypes...)> -{ -public: - typedef _Rp result_type; // extension - -private: - __packaged_task_function<result_type(_ArgTypes...)> __f_; - promise<result_type> __p_; - -public: - // construction and destruction - _LIBCPP_INLINE_VISIBILITY - packaged_task() _NOEXCEPT : __p_(nullptr) {} - template <class _Fp, - class = typename enable_if - < - !is_same< +} + +template <class _Rp> +future<_Rp&>::~future() +{ + if (__state_) + __state_->__release_shared(); +} + +template <class _Rp> +_Rp& +future<_Rp&>::get() +{ + unique_ptr<__shared_count, __release_shared_count> __(__state_); + __assoc_state<_Rp&>* __s = __state_; + __state_ = nullptr; + return __s->copy(); +} + +template <> +class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE future<void> +{ + __assoc_sub_state* __state_; + + explicit future(__assoc_sub_state* __state); + + template <class> friend class promise; + template <class> friend class shared_future; + + template <class _R1, class _Fp> + friend future<_R1> __make_deferred_assoc_state(_Fp&& __f); + template <class _R1, class _Fp> + friend future<_R1> __make_async_assoc_state(_Fp&& __f); + +public: + _LIBCPP_INLINE_VISIBILITY + future() _NOEXCEPT : __state_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY + future(future&& __rhs) _NOEXCEPT + : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} + future(const future&) = delete; + future& operator=(const future&) = delete; + _LIBCPP_INLINE_VISIBILITY + future& operator=(future&& __rhs) _NOEXCEPT + { + future(_VSTD::move(__rhs)).swap(*this); + return *this; + } + + ~future(); + _LIBCPP_INLINE_VISIBILITY + shared_future<void> share() _NOEXCEPT; + + // retrieving the value + void get(); + + _LIBCPP_INLINE_VISIBILITY + void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // functions to check state + _LIBCPP_INLINE_VISIBILITY + bool valid() const _NOEXCEPT {return __state_ != nullptr;} + + _LIBCPP_INLINE_VISIBILITY + void wait() const {__state_->wait();} + template <class _Rep, class _Period> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const + {return __state_->wait_for(__rel_time);} + template <class _Clock, class _Duration> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const + {return __state_->wait_until(__abs_time);} +}; + +template <class _Rp> +inline _LIBCPP_INLINE_VISIBILITY +void +swap(future<_Rp>& __x, future<_Rp>& __y) _NOEXCEPT +{ + __x.swap(__y); +} + +// promise<R> + +template <class _Callable> class packaged_task; + +template <class _Rp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise +{ + __assoc_state<_Rp>* __state_; + + _LIBCPP_INLINE_VISIBILITY + explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} + + template <class> friend class packaged_task; +public: + promise(); + template <class _Alloc> + promise(allocator_arg_t, const _Alloc& __a); + _LIBCPP_INLINE_VISIBILITY + promise(promise&& __rhs) _NOEXCEPT + : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} + promise(const promise& __rhs) = delete; + ~promise(); + + // assignment + _LIBCPP_INLINE_VISIBILITY + promise& operator=(promise&& __rhs) _NOEXCEPT + { + promise(_VSTD::move(__rhs)).swap(*this); + return *this; + } + promise& operator=(const promise& __rhs) = delete; + + _LIBCPP_INLINE_VISIBILITY + void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // retrieving the result + future<_Rp> get_future(); + + // setting the result + void set_value(const _Rp& __r); + void set_value(_Rp&& __r); + void set_exception(exception_ptr __p); + + // setting the result with deferred notification + void set_value_at_thread_exit(const _Rp& __r); + void set_value_at_thread_exit(_Rp&& __r); + void set_exception_at_thread_exit(exception_ptr __p); +}; + +template <class _Rp> +promise<_Rp>::promise() + : __state_(new __assoc_state<_Rp>) +{ +} + +template <class _Rp> +template <class _Alloc> +promise<_Rp>::promise(allocator_arg_t, const _Alloc& __a0) +{ + typedef __assoc_state_alloc<_Rp, _Alloc> _State; + typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; + typedef __allocator_destructor<_A2> _D2; + _A2 __a(__a0); + unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); + ::new ((void*)_VSTD::addressof(*__hold.get())) _State(__a0); + __state_ = _VSTD::addressof(*__hold.release()); +} + +template <class _Rp> +promise<_Rp>::~promise() +{ + if (__state_) + { + if (!__state_->__has_value() && __state_->use_count() > 1) + __state_->set_exception(make_exception_ptr( + future_error(make_error_code(future_errc::broken_promise)) + )); + __state_->__release_shared(); + } +} + +template <class _Rp> +future<_Rp> +promise<_Rp>::get_future() +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + return future<_Rp>(__state_); +} + +template <class _Rp> +void +promise<_Rp>::set_value(const _Rp& __r) +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_value(__r); +} + +template <class _Rp> +void +promise<_Rp>::set_value(_Rp&& __r) +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_value(_VSTD::move(__r)); +} + +template <class _Rp> +void +promise<_Rp>::set_exception(exception_ptr __p) +{ + _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception: received nullptr" ); + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_exception(__p); +} + +template <class _Rp> +void +promise<_Rp>::set_value_at_thread_exit(const _Rp& __r) +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_value_at_thread_exit(__r); +} + +template <class _Rp> +void +promise<_Rp>::set_value_at_thread_exit(_Rp&& __r) +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_value_at_thread_exit(_VSTD::move(__r)); +} + +template <class _Rp> +void +promise<_Rp>::set_exception_at_thread_exit(exception_ptr __p) +{ + _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_exception_at_thread_exit(__p); +} + +// promise<R&> + +template <class _Rp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<_Rp&> +{ + __assoc_state<_Rp&>* __state_; + + _LIBCPP_INLINE_VISIBILITY + explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} + + template <class> friend class packaged_task; + +public: + promise(); + template <class _Allocator> + promise(allocator_arg_t, const _Allocator& __a); + _LIBCPP_INLINE_VISIBILITY + promise(promise&& __rhs) _NOEXCEPT + : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} + promise(const promise& __rhs) = delete; + ~promise(); + + // assignment + _LIBCPP_INLINE_VISIBILITY + promise& operator=(promise&& __rhs) _NOEXCEPT + { + promise(_VSTD::move(__rhs)).swap(*this); + return *this; + } + promise& operator=(const promise& __rhs) = delete; + + _LIBCPP_INLINE_VISIBILITY + void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // retrieving the result + future<_Rp&> get_future(); + + // setting the result + void set_value(_Rp& __r); + void set_exception(exception_ptr __p); + + // setting the result with deferred notification + void set_value_at_thread_exit(_Rp&); + void set_exception_at_thread_exit(exception_ptr __p); +}; + +template <class _Rp> +promise<_Rp&>::promise() + : __state_(new __assoc_state<_Rp&>) +{ +} + +template <class _Rp> +template <class _Alloc> +promise<_Rp&>::promise(allocator_arg_t, const _Alloc& __a0) +{ + typedef __assoc_state_alloc<_Rp&, _Alloc> _State; + typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; + typedef __allocator_destructor<_A2> _D2; + _A2 __a(__a0); + unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); + ::new ((void*)_VSTD::addressof(*__hold.get())) _State(__a0); + __state_ = _VSTD::addressof(*__hold.release()); +} + +template <class _Rp> +promise<_Rp&>::~promise() +{ + if (__state_) + { + if (!__state_->__has_value() && __state_->use_count() > 1) + __state_->set_exception(make_exception_ptr( + future_error(make_error_code(future_errc::broken_promise)) + )); + __state_->__release_shared(); + } +} + +template <class _Rp> +future<_Rp&> +promise<_Rp&>::get_future() +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + return future<_Rp&>(__state_); +} + +template <class _Rp> +void +promise<_Rp&>::set_value(_Rp& __r) +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_value(__r); +} + +template <class _Rp> +void +promise<_Rp&>::set_exception(exception_ptr __p) +{ + _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception: received nullptr" ); + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_exception(__p); +} + +template <class _Rp> +void +promise<_Rp&>::set_value_at_thread_exit(_Rp& __r) +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_value_at_thread_exit(__r); +} + +template <class _Rp> +void +promise<_Rp&>::set_exception_at_thread_exit(exception_ptr __p) +{ + _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_exception_at_thread_exit(__p); +} + +// promise<void> + +template <> +class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<void> +{ + __assoc_sub_state* __state_; + + _LIBCPP_INLINE_VISIBILITY + explicit promise(nullptr_t) _NOEXCEPT : __state_(nullptr) {} + + template <class> friend class packaged_task; + +public: + promise(); + template <class _Allocator> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + promise(allocator_arg_t, const _Allocator& __a); + _LIBCPP_INLINE_VISIBILITY + promise(promise&& __rhs) _NOEXCEPT + : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} + promise(const promise& __rhs) = delete; + ~promise(); + + // assignment + _LIBCPP_INLINE_VISIBILITY + promise& operator=(promise&& __rhs) _NOEXCEPT + { + promise(_VSTD::move(__rhs)).swap(*this); + return *this; + } + promise& operator=(const promise& __rhs) = delete; + + _LIBCPP_INLINE_VISIBILITY + void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // retrieving the result + future<void> get_future(); + + // setting the result + void set_value(); + void set_exception(exception_ptr __p); + + // setting the result with deferred notification + void set_value_at_thread_exit(); + void set_exception_at_thread_exit(exception_ptr __p); +}; + +template <class _Alloc> +promise<void>::promise(allocator_arg_t, const _Alloc& __a0) +{ + typedef __assoc_sub_state_alloc<_Alloc> _State; + typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; + typedef __allocator_destructor<_A2> _D2; + _A2 __a(__a0); + unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); + ::new ((void*)_VSTD::addressof(*__hold.get())) _State(__a0); + __state_ = _VSTD::addressof(*__hold.release()); +} + +template <class _Rp> +inline _LIBCPP_INLINE_VISIBILITY +void +swap(promise<_Rp>& __x, promise<_Rp>& __y) _NOEXCEPT +{ + __x.swap(__y); +} + +template <class _Rp, class _Alloc> + struct _LIBCPP_TEMPLATE_VIS uses_allocator<promise<_Rp>, _Alloc> + : public true_type {}; + +// packaged_task + +template<class _Fp> class __packaged_task_base; + +template<class _Rp, class ..._ArgTypes> +class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_base<_Rp(_ArgTypes...)> +{ + __packaged_task_base(const __packaged_task_base&); + __packaged_task_base& operator=(const __packaged_task_base&); +public: + _LIBCPP_INLINE_VISIBILITY + __packaged_task_base() {} + _LIBCPP_INLINE_VISIBILITY + virtual ~__packaged_task_base() {} + virtual void __move_to(__packaged_task_base*) _NOEXCEPT = 0; + virtual void destroy() = 0; + virtual void destroy_deallocate() = 0; + virtual _Rp operator()(_ArgTypes&& ...) = 0; +}; + +template<class _FD, class _Alloc, class _FB> class __packaged_task_func; + +template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> +class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)> + : public __packaged_task_base<_Rp(_ArgTypes...)> +{ + __compressed_pair<_Fp, _Alloc> __f_; +public: + _LIBCPP_INLINE_VISIBILITY + explicit __packaged_task_func(const _Fp& __f) : __f_(__f, __default_init_tag()) {} + _LIBCPP_INLINE_VISIBILITY + explicit __packaged_task_func(_Fp&& __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} + _LIBCPP_INLINE_VISIBILITY + __packaged_task_func(const _Fp& __f, const _Alloc& __a) + : __f_(__f, __a) {} + _LIBCPP_INLINE_VISIBILITY + __packaged_task_func(_Fp&& __f, const _Alloc& __a) + : __f_(_VSTD::move(__f), __a) {} + virtual void __move_to(__packaged_task_base<_Rp(_ArgTypes...)>*) _NOEXCEPT; + virtual void destroy(); + virtual void destroy_deallocate(); + virtual _Rp operator()(_ArgTypes&& ... __args); +}; + +template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> +void +__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__move_to( + __packaged_task_base<_Rp(_ArgTypes...)>* __p) _NOEXCEPT +{ + ::new ((void*)__p) __packaged_task_func(_VSTD::move(__f_.first()), _VSTD::move(__f_.second())); +} + +template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> +void +__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() +{ + __f_.~__compressed_pair<_Fp, _Alloc>(); +} + +template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> +void +__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() +{ + typedef typename __allocator_traits_rebind<_Alloc, __packaged_task_func>::type _Ap; + typedef allocator_traits<_Ap> _ATraits; + typedef pointer_traits<typename _ATraits::pointer> _PTraits; + _Ap __a(__f_.second()); + __f_.~__compressed_pair<_Fp, _Alloc>(); + __a.deallocate(_PTraits::pointer_to(*this), 1); +} + +template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> +_Rp +__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) +{ + return _VSTD::__invoke(__f_.first(), _VSTD::forward<_ArgTypes>(__arg)...); +} + +template <class _Callable> class __packaged_task_function; + +template<class _Rp, class ..._ArgTypes> +class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_function<_Rp(_ArgTypes...)> +{ + typedef __packaged_task_base<_Rp(_ArgTypes...)> __base; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_NO_CFI + __base* __get_buf() { return (__base*)&__buf_; } + + typename aligned_storage<3*sizeof(void*)>::type __buf_; + __base* __f_; + +public: + typedef _Rp result_type; + + // construct/copy/destroy: + _LIBCPP_INLINE_VISIBILITY + __packaged_task_function() _NOEXCEPT : __f_(nullptr) {} + template<class _Fp> + __packaged_task_function(_Fp&& __f); + template<class _Fp, class _Alloc> + __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f); + + __packaged_task_function(__packaged_task_function&&) _NOEXCEPT; + __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT; + + __packaged_task_function(const __packaged_task_function&) = delete; + __packaged_task_function& operator=(const __packaged_task_function&) = delete; + + ~__packaged_task_function(); + + void swap(__packaged_task_function&) _NOEXCEPT; + + _LIBCPP_INLINE_VISIBILITY + _Rp operator()(_ArgTypes...) const; +}; + +template<class _Rp, class ..._ArgTypes> +__packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(__packaged_task_function&& __f) _NOEXCEPT +{ + if (__f.__f_ == nullptr) + __f_ = nullptr; + else if (__f.__f_ == __f.__get_buf()) + { + __f.__f_->__move_to(__get_buf()); + __f_ = (__base*)&__buf_; + } + else + { + __f_ = __f.__f_; + __f.__f_ = nullptr; + } +} + +template<class _Rp, class ..._ArgTypes> +template <class _Fp> +__packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f) + : __f_(nullptr) +{ + typedef typename remove_reference<typename decay<_Fp>::type>::type _FR; + typedef __packaged_task_func<_FR, allocator<_FR>, _Rp(_ArgTypes...)> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + ::new ((void*)&__buf_) _FF(_VSTD::forward<_Fp>(__f)); + __f_ = (__base*)&__buf_; + } + else + { + typedef allocator<_FF> _Ap; + _Ap __a; + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new ((void*)__hold.get()) _FF(_VSTD::forward<_Fp>(__f), allocator<_FR>(__a)); + __f_ = __hold.release(); + } +} + +template<class _Rp, class ..._ArgTypes> +template <class _Fp, class _Alloc> +__packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function( + allocator_arg_t, const _Alloc& __a0, _Fp&& __f) + : __f_(nullptr) +{ + typedef typename remove_reference<typename decay<_Fp>::type>::type _FR; + typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new ((void*)__f_) _FF(_VSTD::forward<_Fp>(__f)); + } + else + { + typedef typename __allocator_traits_rebind<_Alloc, _FF>::type _Ap; + _Ap __a(__a0); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new ((void*)_VSTD::addressof(*__hold.get())) + _FF(_VSTD::forward<_Fp>(__f), _Alloc(__a)); + __f_ = _VSTD::addressof(*__hold.release()); + } +} + +template<class _Rp, class ..._ArgTypes> +__packaged_task_function<_Rp(_ArgTypes...)>& +__packaged_task_function<_Rp(_ArgTypes...)>::operator=(__packaged_task_function&& __f) _NOEXCEPT +{ + if (__f_ == __get_buf()) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); + __f_ = nullptr; + if (__f.__f_ == nullptr) + __f_ = nullptr; + else if (__f.__f_ == __f.__get_buf()) + { + __f.__f_->__move_to(__get_buf()); + __f_ = __get_buf(); + } + else + { + __f_ = __f.__f_; + __f.__f_ = nullptr; + } + return *this; +} + +template<class _Rp, class ..._ArgTypes> +__packaged_task_function<_Rp(_ArgTypes...)>::~__packaged_task_function() +{ + if (__f_ == __get_buf()) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); +} + +template<class _Rp, class ..._ArgTypes> +_LIBCPP_NO_CFI +void +__packaged_task_function<_Rp(_ArgTypes...)>::swap(__packaged_task_function& __f) _NOEXCEPT +{ + if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) + { + typename aligned_storage<sizeof(__buf_)>::type __tempbuf; + __base* __t = (__base*)&__tempbuf; + __f_->__move_to(__t); + __f_->destroy(); + __f_ = nullptr; + __f.__f_->__move_to((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = nullptr; + __f_ = (__base*)&__buf_; + __t->__move_to((__base*)&__f.__buf_); + __t->destroy(); + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f_ == (__base*)&__buf_) + { + __f_->__move_to((__base*)&__f.__buf_); + __f_->destroy(); + __f_ = __f.__f_; + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f.__f_ == (__base*)&__f.__buf_) + { + __f.__f_->__move_to((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = __f_; + __f_ = (__base*)&__buf_; + } + else + _VSTD::swap(__f_, __f.__f_); +} + +template<class _Rp, class ..._ArgTypes> +inline +_Rp +__packaged_task_function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const +{ + return (*__f_)(_VSTD::forward<_ArgTypes>(__arg)...); +} + +template<class _Rp, class ..._ArgTypes> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<_Rp(_ArgTypes...)> +{ +public: + typedef _Rp result_type; // extension + +private: + __packaged_task_function<result_type(_ArgTypes...)> __f_; + promise<result_type> __p_; + +public: + // construction and destruction + _LIBCPP_INLINE_VISIBILITY + packaged_task() _NOEXCEPT : __p_(nullptr) {} + template <class _Fp, + class = typename enable_if + < + !is_same< typename __uncvref<_Fp>::type, - packaged_task - >::value - >::type - > - _LIBCPP_INLINE_VISIBILITY - explicit packaged_task(_Fp&& __f) : __f_(_VSTD::forward<_Fp>(__f)) {} - template <class _Fp, class _Allocator, - class = typename enable_if - < - !is_same< + packaged_task + >::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + explicit packaged_task(_Fp&& __f) : __f_(_VSTD::forward<_Fp>(__f)) {} + template <class _Fp, class _Allocator, + class = typename enable_if + < + !is_same< typename __uncvref<_Fp>::type, - packaged_task - >::value - >::type - > - _LIBCPP_INLINE_VISIBILITY - packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) - : __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)), - __p_(allocator_arg, __a) {} - // ~packaged_task() = default; - - // no copy - packaged_task(const packaged_task&) = delete; - packaged_task& operator=(const packaged_task&) = delete; - - // move support - _LIBCPP_INLINE_VISIBILITY - packaged_task(packaged_task&& __other) _NOEXCEPT - : __f_(_VSTD::move(__other.__f_)), __p_(_VSTD::move(__other.__p_)) {} - _LIBCPP_INLINE_VISIBILITY - packaged_task& operator=(packaged_task&& __other) _NOEXCEPT - { - __f_ = _VSTD::move(__other.__f_); - __p_ = _VSTD::move(__other.__p_); - return *this; - } - _LIBCPP_INLINE_VISIBILITY - void swap(packaged_task& __other) _NOEXCEPT - { - __f_.swap(__other.__f_); - __p_.swap(__other.__p_); - } - - _LIBCPP_INLINE_VISIBILITY - bool valid() const _NOEXCEPT {return __p_.__state_ != nullptr;} - - // result retrieval - _LIBCPP_INLINE_VISIBILITY - future<result_type> get_future() {return __p_.get_future();} - - // execution - void operator()(_ArgTypes... __args); - void make_ready_at_thread_exit(_ArgTypes... __args); - - void reset(); -}; - -template<class _Rp, class ..._ArgTypes> -void -packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) -{ - if (__p_.__state_ == nullptr) - __throw_future_error(future_errc::no_state); - if (__p_.__state_->__has_value()) - __throw_future_error(future_errc::promise_already_satisfied); -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - __p_.set_value(__f_(_VSTD::forward<_ArgTypes>(__args)...)); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __p_.set_exception(current_exception()); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template<class _Rp, class ..._ArgTypes> -void -packaged_task<_Rp(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) -{ - if (__p_.__state_ == nullptr) - __throw_future_error(future_errc::no_state); - if (__p_.__state_->__has_value()) - __throw_future_error(future_errc::promise_already_satisfied); -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - __p_.set_value_at_thread_exit(__f_(_VSTD::forward<_ArgTypes>(__args)...)); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __p_.set_exception_at_thread_exit(current_exception()); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template<class _Rp, class ..._ArgTypes> -void -packaged_task<_Rp(_ArgTypes...)>::reset() -{ - if (!valid()) - __throw_future_error(future_errc::no_state); - __p_ = promise<result_type>(); -} - -template<class ..._ArgTypes> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<void(_ArgTypes...)> -{ -public: - typedef void result_type; // extension - -private: - __packaged_task_function<result_type(_ArgTypes...)> __f_; - promise<result_type> __p_; - -public: - // construction and destruction - _LIBCPP_INLINE_VISIBILITY - packaged_task() _NOEXCEPT : __p_(nullptr) {} - template <class _Fp, - class = typename enable_if - < - !is_same< + packaged_task + >::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) + : __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)), + __p_(allocator_arg, __a) {} + // ~packaged_task() = default; + + // no copy + packaged_task(const packaged_task&) = delete; + packaged_task& operator=(const packaged_task&) = delete; + + // move support + _LIBCPP_INLINE_VISIBILITY + packaged_task(packaged_task&& __other) _NOEXCEPT + : __f_(_VSTD::move(__other.__f_)), __p_(_VSTD::move(__other.__p_)) {} + _LIBCPP_INLINE_VISIBILITY + packaged_task& operator=(packaged_task&& __other) _NOEXCEPT + { + __f_ = _VSTD::move(__other.__f_); + __p_ = _VSTD::move(__other.__p_); + return *this; + } + _LIBCPP_INLINE_VISIBILITY + void swap(packaged_task& __other) _NOEXCEPT + { + __f_.swap(__other.__f_); + __p_.swap(__other.__p_); + } + + _LIBCPP_INLINE_VISIBILITY + bool valid() const _NOEXCEPT {return __p_.__state_ != nullptr;} + + // result retrieval + _LIBCPP_INLINE_VISIBILITY + future<result_type> get_future() {return __p_.get_future();} + + // execution + void operator()(_ArgTypes... __args); + void make_ready_at_thread_exit(_ArgTypes... __args); + + void reset(); +}; + +template<class _Rp, class ..._ArgTypes> +void +packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) +{ + if (__p_.__state_ == nullptr) + __throw_future_error(future_errc::no_state); + if (__p_.__state_->__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + __p_.set_value(__f_(_VSTD::forward<_ArgTypes>(__args)...)); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __p_.set_exception(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template<class _Rp, class ..._ArgTypes> +void +packaged_task<_Rp(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) +{ + if (__p_.__state_ == nullptr) + __throw_future_error(future_errc::no_state); + if (__p_.__state_->__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + __p_.set_value_at_thread_exit(__f_(_VSTD::forward<_ArgTypes>(__args)...)); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __p_.set_exception_at_thread_exit(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template<class _Rp, class ..._ArgTypes> +void +packaged_task<_Rp(_ArgTypes...)>::reset() +{ + if (!valid()) + __throw_future_error(future_errc::no_state); + __p_ = promise<result_type>(); +} + +template<class ..._ArgTypes> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<void(_ArgTypes...)> +{ +public: + typedef void result_type; // extension + +private: + __packaged_task_function<result_type(_ArgTypes...)> __f_; + promise<result_type> __p_; + +public: + // construction and destruction + _LIBCPP_INLINE_VISIBILITY + packaged_task() _NOEXCEPT : __p_(nullptr) {} + template <class _Fp, + class = typename enable_if + < + !is_same< typename __uncvref<_Fp>::type, - packaged_task - >::value - >::type - > - _LIBCPP_INLINE_VISIBILITY - explicit packaged_task(_Fp&& __f) : __f_(_VSTD::forward<_Fp>(__f)) {} - template <class _Fp, class _Allocator, - class = typename enable_if - < - !is_same< + packaged_task + >::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + explicit packaged_task(_Fp&& __f) : __f_(_VSTD::forward<_Fp>(__f)) {} + template <class _Fp, class _Allocator, + class = typename enable_if + < + !is_same< typename __uncvref<_Fp>::type, - packaged_task - >::value - >::type + packaged_task + >::value + >::type > - _LIBCPP_INLINE_VISIBILITY - packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) - : __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)), - __p_(allocator_arg, __a) {} - // ~packaged_task() = default; - - // no copy - packaged_task(const packaged_task&) = delete; - packaged_task& operator=(const packaged_task&) = delete; - - // move support - _LIBCPP_INLINE_VISIBILITY - packaged_task(packaged_task&& __other) _NOEXCEPT - : __f_(_VSTD::move(__other.__f_)), __p_(_VSTD::move(__other.__p_)) {} - _LIBCPP_INLINE_VISIBILITY - packaged_task& operator=(packaged_task&& __other) _NOEXCEPT - { - __f_ = _VSTD::move(__other.__f_); - __p_ = _VSTD::move(__other.__p_); - return *this; - } - _LIBCPP_INLINE_VISIBILITY - void swap(packaged_task& __other) _NOEXCEPT - { - __f_.swap(__other.__f_); - __p_.swap(__other.__p_); - } - - _LIBCPP_INLINE_VISIBILITY - bool valid() const _NOEXCEPT {return __p_.__state_ != nullptr;} - - // result retrieval - _LIBCPP_INLINE_VISIBILITY - future<result_type> get_future() {return __p_.get_future();} - - // execution - void operator()(_ArgTypes... __args); - void make_ready_at_thread_exit(_ArgTypes... __args); - - void reset(); -}; - -template<class ..._ArgTypes> -void -packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) -{ - if (__p_.__state_ == nullptr) - __throw_future_error(future_errc::no_state); - if (__p_.__state_->__has_value()) - __throw_future_error(future_errc::promise_already_satisfied); -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - __f_(_VSTD::forward<_ArgTypes>(__args)...); - __p_.set_value(); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __p_.set_exception(current_exception()); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template<class ..._ArgTypes> -void -packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) -{ - if (__p_.__state_ == nullptr) - __throw_future_error(future_errc::no_state); - if (__p_.__state_->__has_value()) - __throw_future_error(future_errc::promise_already_satisfied); -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - __f_(_VSTD::forward<_ArgTypes>(__args)...); - __p_.set_value_at_thread_exit(); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __p_.set_exception_at_thread_exit(current_exception()); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template<class ..._ArgTypes> -void -packaged_task<void(_ArgTypes...)>::reset() -{ - if (!valid()) - __throw_future_error(future_errc::no_state); - __p_ = promise<result_type>(); -} - -template <class _Rp, class... _ArgTypes> -inline _LIBCPP_INLINE_VISIBILITY -void -swap(packaged_task<_Rp(_ArgTypes...)>& __x, packaged_task<_Rp(_ArgTypes...)>& __y) _NOEXCEPT -{ - __x.swap(__y); -} - -template <class _Callable, class _Alloc> -struct _LIBCPP_TEMPLATE_VIS uses_allocator<packaged_task<_Callable>, _Alloc> - : public true_type {}; - -template <class _Rp, class _Fp> -_LIBCPP_INLINE_VISIBILITY future<_Rp> -__make_deferred_assoc_state(_Fp&& __f) -{ - unique_ptr<__deferred_assoc_state<_Rp, _Fp>, __release_shared_count> - __h(new __deferred_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f))); - return future<_Rp>(__h.get()); -} - -template <class _Rp, class _Fp> -_LIBCPP_INLINE_VISIBILITY future<_Rp> -__make_async_assoc_state(_Fp&& __f) -{ - unique_ptr<__async_assoc_state<_Rp, _Fp>, __release_shared_count> - __h(new __async_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f))); - _VSTD::thread(&__async_assoc_state<_Rp, _Fp>::__execute, __h.get()).detach(); - return future<_Rp>(__h.get()); -} - -#ifndef _LIBCPP_CXX03_LANG - -template <class _Fp, class... _Args> -class _LIBCPP_HIDDEN __async_func -{ - tuple<_Fp, _Args...> __f_; - -public: - typedef typename __invoke_of<_Fp, _Args...>::type _Rp; - - _LIBCPP_INLINE_VISIBILITY - explicit __async_func(_Fp&& __f, _Args&&... __args) - : __f_(_VSTD::move(__f), _VSTD::move(__args)...) {} - - _LIBCPP_INLINE_VISIBILITY - __async_func(__async_func&& __f) : __f_(_VSTD::move(__f.__f_)) {} - - _Rp operator()() - { - typedef typename __make_tuple_indices<1+sizeof...(_Args), 1>::type _Index; - return __execute(_Index()); - } -private: - template <size_t ..._Indices> - _Rp - __execute(__tuple_indices<_Indices...>) - { - return _VSTD::__invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indices>(__f_))...); - } -}; - -inline _LIBCPP_INLINE_VISIBILITY bool __does_policy_contain(launch __policy, launch __value ) -{ return (int(__policy) & int(__value)) != 0; } - -template <class _Fp, class... _Args> -_LIBCPP_NODISCARD_AFTER_CXX17 -future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type> -async(launch __policy, _Fp&& __f, _Args&&... __args) -{ - typedef __async_func<typename decay<_Fp>::type, typename decay<_Args>::type...> _BF; - typedef typename _BF::_Rp _Rp; - -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif - if (__does_policy_contain(__policy, launch::async)) - return _VSTD::__make_async_assoc_state<_Rp>(_BF(_VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)), - _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...)); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch ( ... ) { if (__policy == launch::async) throw ; } -#endif - - if (__does_policy_contain(__policy, launch::deferred)) - return _VSTD::__make_deferred_assoc_state<_Rp>(_BF(_VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)), - _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...)); - return future<_Rp>{}; -} - -template <class _Fp, class... _Args> -_LIBCPP_NODISCARD_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY -future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type> -async(_Fp&& __f, _Args&&... __args) -{ - return _VSTD::async(launch::any, _VSTD::forward<_Fp>(__f), - _VSTD::forward<_Args>(__args)...); -} - -#endif // C++03 - -// shared_future - -template <class _Rp> -class _LIBCPP_TEMPLATE_VIS shared_future -{ - __assoc_state<_Rp>* __state_; - -public: - _LIBCPP_INLINE_VISIBILITY - shared_future() _NOEXCEPT : __state_(nullptr) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY + packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) + : __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)), + __p_(allocator_arg, __a) {} + // ~packaged_task() = default; + + // no copy + packaged_task(const packaged_task&) = delete; + packaged_task& operator=(const packaged_task&) = delete; + + // move support + _LIBCPP_INLINE_VISIBILITY + packaged_task(packaged_task&& __other) _NOEXCEPT + : __f_(_VSTD::move(__other.__f_)), __p_(_VSTD::move(__other.__p_)) {} + _LIBCPP_INLINE_VISIBILITY + packaged_task& operator=(packaged_task&& __other) _NOEXCEPT + { + __f_ = _VSTD::move(__other.__f_); + __p_ = _VSTD::move(__other.__p_); + return *this; + } + _LIBCPP_INLINE_VISIBILITY + void swap(packaged_task& __other) _NOEXCEPT + { + __f_.swap(__other.__f_); + __p_.swap(__other.__p_); + } + + _LIBCPP_INLINE_VISIBILITY + bool valid() const _NOEXCEPT {return __p_.__state_ != nullptr;} + + // result retrieval + _LIBCPP_INLINE_VISIBILITY + future<result_type> get_future() {return __p_.get_future();} + + // execution + void operator()(_ArgTypes... __args); + void make_ready_at_thread_exit(_ArgTypes... __args); + + void reset(); +}; + +template<class ..._ArgTypes> +void +packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) +{ + if (__p_.__state_ == nullptr) + __throw_future_error(future_errc::no_state); + if (__p_.__state_->__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + __f_(_VSTD::forward<_ArgTypes>(__args)...); + __p_.set_value(); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __p_.set_exception(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template<class ..._ArgTypes> +void +packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) +{ + if (__p_.__state_ == nullptr) + __throw_future_error(future_errc::no_state); + if (__p_.__state_->__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + __f_(_VSTD::forward<_ArgTypes>(__args)...); + __p_.set_value_at_thread_exit(); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __p_.set_exception_at_thread_exit(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template<class ..._ArgTypes> +void +packaged_task<void(_ArgTypes...)>::reset() +{ + if (!valid()) + __throw_future_error(future_errc::no_state); + __p_ = promise<result_type>(); +} + +template <class _Rp, class... _ArgTypes> +inline _LIBCPP_INLINE_VISIBILITY +void +swap(packaged_task<_Rp(_ArgTypes...)>& __x, packaged_task<_Rp(_ArgTypes...)>& __y) _NOEXCEPT +{ + __x.swap(__y); +} + +template <class _Callable, class _Alloc> +struct _LIBCPP_TEMPLATE_VIS uses_allocator<packaged_task<_Callable>, _Alloc> + : public true_type {}; + +template <class _Rp, class _Fp> +_LIBCPP_INLINE_VISIBILITY future<_Rp> +__make_deferred_assoc_state(_Fp&& __f) +{ + unique_ptr<__deferred_assoc_state<_Rp, _Fp>, __release_shared_count> + __h(new __deferred_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f))); + return future<_Rp>(__h.get()); +} + +template <class _Rp, class _Fp> +_LIBCPP_INLINE_VISIBILITY future<_Rp> +__make_async_assoc_state(_Fp&& __f) +{ + unique_ptr<__async_assoc_state<_Rp, _Fp>, __release_shared_count> + __h(new __async_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f))); + _VSTD::thread(&__async_assoc_state<_Rp, _Fp>::__execute, __h.get()).detach(); + return future<_Rp>(__h.get()); +} + +#ifndef _LIBCPP_CXX03_LANG + +template <class _Fp, class... _Args> +class _LIBCPP_HIDDEN __async_func +{ + tuple<_Fp, _Args...> __f_; + +public: + typedef typename __invoke_of<_Fp, _Args...>::type _Rp; + + _LIBCPP_INLINE_VISIBILITY + explicit __async_func(_Fp&& __f, _Args&&... __args) + : __f_(_VSTD::move(__f), _VSTD::move(__args)...) {} + + _LIBCPP_INLINE_VISIBILITY + __async_func(__async_func&& __f) : __f_(_VSTD::move(__f.__f_)) {} + + _Rp operator()() + { + typedef typename __make_tuple_indices<1+sizeof...(_Args), 1>::type _Index; + return __execute(_Index()); + } +private: + template <size_t ..._Indices> + _Rp + __execute(__tuple_indices<_Indices...>) + { + return _VSTD::__invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indices>(__f_))...); + } +}; + +inline _LIBCPP_INLINE_VISIBILITY bool __does_policy_contain(launch __policy, launch __value ) +{ return (int(__policy) & int(__value)) != 0; } + +template <class _Fp, class... _Args> +_LIBCPP_NODISCARD_AFTER_CXX17 +future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type> +async(launch __policy, _Fp&& __f, _Args&&... __args) +{ + typedef __async_func<typename decay<_Fp>::type, typename decay<_Args>::type...> _BF; + typedef typename _BF::_Rp _Rp; + +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif + if (__does_policy_contain(__policy, launch::async)) + return _VSTD::__make_async_assoc_state<_Rp>(_BF(_VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)), + _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...)); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch ( ... ) { if (__policy == launch::async) throw ; } +#endif + + if (__does_policy_contain(__policy, launch::deferred)) + return _VSTD::__make_deferred_assoc_state<_Rp>(_BF(_VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)), + _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...)); + return future<_Rp>{}; +} + +template <class _Fp, class... _Args> +_LIBCPP_NODISCARD_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY +future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type> +async(_Fp&& __f, _Args&&... __args) +{ + return _VSTD::async(launch::any, _VSTD::forward<_Fp>(__f), + _VSTD::forward<_Args>(__args)...); +} + +#endif // C++03 + +// shared_future + +template <class _Rp> +class _LIBCPP_TEMPLATE_VIS shared_future +{ + __assoc_state<_Rp>* __state_; + +public: + _LIBCPP_INLINE_VISIBILITY + shared_future() _NOEXCEPT : __state_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY shared_future(const shared_future& __rhs) _NOEXCEPT : __state_(__rhs.__state_) - {if (__state_) __state_->__add_shared();} - _LIBCPP_INLINE_VISIBILITY - shared_future(future<_Rp>&& __f) _NOEXCEPT : __state_(__f.__state_) - {__f.__state_ = nullptr;} - _LIBCPP_INLINE_VISIBILITY - shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) - {__rhs.__state_ = nullptr;} - ~shared_future(); + {if (__state_) __state_->__add_shared();} + _LIBCPP_INLINE_VISIBILITY + shared_future(future<_Rp>&& __f) _NOEXCEPT : __state_(__f.__state_) + {__f.__state_ = nullptr;} + _LIBCPP_INLINE_VISIBILITY + shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) + {__rhs.__state_ = nullptr;} + ~shared_future(); shared_future& operator=(const shared_future& __rhs) _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - shared_future& operator=(shared_future&& __rhs) _NOEXCEPT - { - shared_future(_VSTD::move(__rhs)).swap(*this); - return *this; - } - - // retrieving the value - _LIBCPP_INLINE_VISIBILITY - const _Rp& get() const {return __state_->copy();} - - _LIBCPP_INLINE_VISIBILITY - void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // functions to check state - _LIBCPP_INLINE_VISIBILITY - bool valid() const _NOEXCEPT {return __state_ != nullptr;} - - _LIBCPP_INLINE_VISIBILITY - void wait() const {__state_->wait();} - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const - {return __state_->wait_for(__rel_time);} - template <class _Clock, class _Duration> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const - {return __state_->wait_until(__abs_time);} -}; - -template <class _Rp> -shared_future<_Rp>::~shared_future() -{ - if (__state_) - __state_->__release_shared(); -} - -template <class _Rp> -shared_future<_Rp>& + _LIBCPP_INLINE_VISIBILITY + shared_future& operator=(shared_future&& __rhs) _NOEXCEPT + { + shared_future(_VSTD::move(__rhs)).swap(*this); + return *this; + } + + // retrieving the value + _LIBCPP_INLINE_VISIBILITY + const _Rp& get() const {return __state_->copy();} + + _LIBCPP_INLINE_VISIBILITY + void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // functions to check state + _LIBCPP_INLINE_VISIBILITY + bool valid() const _NOEXCEPT {return __state_ != nullptr;} + + _LIBCPP_INLINE_VISIBILITY + void wait() const {__state_->wait();} + template <class _Rep, class _Period> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const + {return __state_->wait_for(__rel_time);} + template <class _Clock, class _Duration> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const + {return __state_->wait_until(__abs_time);} +}; + +template <class _Rp> +shared_future<_Rp>::~shared_future() +{ + if (__state_) + __state_->__release_shared(); +} + +template <class _Rp> +shared_future<_Rp>& shared_future<_Rp>::operator=(const shared_future& __rhs) _NOEXCEPT -{ - if (__rhs.__state_) - __rhs.__state_->__add_shared(); - if (__state_) - __state_->__release_shared(); - __state_ = __rhs.__state_; - return *this; -} - -template <class _Rp> -class _LIBCPP_TEMPLATE_VIS shared_future<_Rp&> -{ - __assoc_state<_Rp&>* __state_; - -public: - _LIBCPP_INLINE_VISIBILITY - shared_future() _NOEXCEPT : __state_(nullptr) {} - _LIBCPP_INLINE_VISIBILITY - shared_future(const shared_future& __rhs) : __state_(__rhs.__state_) - {if (__state_) __state_->__add_shared();} - _LIBCPP_INLINE_VISIBILITY - shared_future(future<_Rp&>&& __f) _NOEXCEPT : __state_(__f.__state_) - {__f.__state_ = nullptr;} - _LIBCPP_INLINE_VISIBILITY - shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) - {__rhs.__state_ = nullptr;} - ~shared_future(); - shared_future& operator=(const shared_future& __rhs); - _LIBCPP_INLINE_VISIBILITY - shared_future& operator=(shared_future&& __rhs) _NOEXCEPT - { - shared_future(_VSTD::move(__rhs)).swap(*this); - return *this; - } - - // retrieving the value - _LIBCPP_INLINE_VISIBILITY - _Rp& get() const {return __state_->copy();} - - _LIBCPP_INLINE_VISIBILITY - void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // functions to check state - _LIBCPP_INLINE_VISIBILITY - bool valid() const _NOEXCEPT {return __state_ != nullptr;} - - _LIBCPP_INLINE_VISIBILITY - void wait() const {__state_->wait();} - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const - {return __state_->wait_for(__rel_time);} - template <class _Clock, class _Duration> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const - {return __state_->wait_until(__abs_time);} -}; - -template <class _Rp> -shared_future<_Rp&>::~shared_future() -{ - if (__state_) - __state_->__release_shared(); -} - -template <class _Rp> -shared_future<_Rp&>& -shared_future<_Rp&>::operator=(const shared_future& __rhs) -{ - if (__rhs.__state_) - __rhs.__state_->__add_shared(); - if (__state_) - __state_->__release_shared(); - __state_ = __rhs.__state_; - return *this; -} - -template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE shared_future<void> -{ - __assoc_sub_state* __state_; - -public: - _LIBCPP_INLINE_VISIBILITY - shared_future() _NOEXCEPT : __state_(nullptr) {} - _LIBCPP_INLINE_VISIBILITY - shared_future(const shared_future& __rhs) : __state_(__rhs.__state_) - {if (__state_) __state_->__add_shared();} - _LIBCPP_INLINE_VISIBILITY - shared_future(future<void>&& __f) _NOEXCEPT : __state_(__f.__state_) - {__f.__state_ = nullptr;} - _LIBCPP_INLINE_VISIBILITY - shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) - {__rhs.__state_ = nullptr;} - ~shared_future(); - shared_future& operator=(const shared_future& __rhs); - _LIBCPP_INLINE_VISIBILITY - shared_future& operator=(shared_future&& __rhs) _NOEXCEPT - { - shared_future(_VSTD::move(__rhs)).swap(*this); - return *this; - } - - // retrieving the value - _LIBCPP_INLINE_VISIBILITY - void get() const {__state_->copy();} - - _LIBCPP_INLINE_VISIBILITY - void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} - - // functions to check state - _LIBCPP_INLINE_VISIBILITY - bool valid() const _NOEXCEPT {return __state_ != nullptr;} - - _LIBCPP_INLINE_VISIBILITY - void wait() const {__state_->wait();} - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const - {return __state_->wait_for(__rel_time);} - template <class _Clock, class _Duration> - _LIBCPP_INLINE_VISIBILITY - future_status - wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const - {return __state_->wait_until(__abs_time);} -}; - -template <class _Rp> -inline _LIBCPP_INLINE_VISIBILITY -void -swap(shared_future<_Rp>& __x, shared_future<_Rp>& __y) _NOEXCEPT -{ - __x.swap(__y); -} - -template <class _Rp> -inline -shared_future<_Rp> -future<_Rp>::share() _NOEXCEPT -{ - return shared_future<_Rp>(_VSTD::move(*this)); -} - -template <class _Rp> -inline -shared_future<_Rp&> -future<_Rp&>::share() _NOEXCEPT -{ - return shared_future<_Rp&>(_VSTD::move(*this)); -} - -inline -shared_future<void> -future<void>::share() _NOEXCEPT -{ - return shared_future<void>(_VSTD::move(*this)); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !_LIBCPP_HAS_NO_THREADS - -#endif // _LIBCPP_FUTURE +{ + if (__rhs.__state_) + __rhs.__state_->__add_shared(); + if (__state_) + __state_->__release_shared(); + __state_ = __rhs.__state_; + return *this; +} + +template <class _Rp> +class _LIBCPP_TEMPLATE_VIS shared_future<_Rp&> +{ + __assoc_state<_Rp&>* __state_; + +public: + _LIBCPP_INLINE_VISIBILITY + shared_future() _NOEXCEPT : __state_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY + shared_future(const shared_future& __rhs) : __state_(__rhs.__state_) + {if (__state_) __state_->__add_shared();} + _LIBCPP_INLINE_VISIBILITY + shared_future(future<_Rp&>&& __f) _NOEXCEPT : __state_(__f.__state_) + {__f.__state_ = nullptr;} + _LIBCPP_INLINE_VISIBILITY + shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) + {__rhs.__state_ = nullptr;} + ~shared_future(); + shared_future& operator=(const shared_future& __rhs); + _LIBCPP_INLINE_VISIBILITY + shared_future& operator=(shared_future&& __rhs) _NOEXCEPT + { + shared_future(_VSTD::move(__rhs)).swap(*this); + return *this; + } + + // retrieving the value + _LIBCPP_INLINE_VISIBILITY + _Rp& get() const {return __state_->copy();} + + _LIBCPP_INLINE_VISIBILITY + void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // functions to check state + _LIBCPP_INLINE_VISIBILITY + bool valid() const _NOEXCEPT {return __state_ != nullptr;} + + _LIBCPP_INLINE_VISIBILITY + void wait() const {__state_->wait();} + template <class _Rep, class _Period> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const + {return __state_->wait_for(__rel_time);} + template <class _Clock, class _Duration> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const + {return __state_->wait_until(__abs_time);} +}; + +template <class _Rp> +shared_future<_Rp&>::~shared_future() +{ + if (__state_) + __state_->__release_shared(); +} + +template <class _Rp> +shared_future<_Rp&>& +shared_future<_Rp&>::operator=(const shared_future& __rhs) +{ + if (__rhs.__state_) + __rhs.__state_->__add_shared(); + if (__state_) + __state_->__release_shared(); + __state_ = __rhs.__state_; + return *this; +} + +template <> +class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE shared_future<void> +{ + __assoc_sub_state* __state_; + +public: + _LIBCPP_INLINE_VISIBILITY + shared_future() _NOEXCEPT : __state_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY + shared_future(const shared_future& __rhs) : __state_(__rhs.__state_) + {if (__state_) __state_->__add_shared();} + _LIBCPP_INLINE_VISIBILITY + shared_future(future<void>&& __f) _NOEXCEPT : __state_(__f.__state_) + {__f.__state_ = nullptr;} + _LIBCPP_INLINE_VISIBILITY + shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) + {__rhs.__state_ = nullptr;} + ~shared_future(); + shared_future& operator=(const shared_future& __rhs); + _LIBCPP_INLINE_VISIBILITY + shared_future& operator=(shared_future&& __rhs) _NOEXCEPT + { + shared_future(_VSTD::move(__rhs)).swap(*this); + return *this; + } + + // retrieving the value + _LIBCPP_INLINE_VISIBILITY + void get() const {__state_->copy();} + + _LIBCPP_INLINE_VISIBILITY + void swap(shared_future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} + + // functions to check state + _LIBCPP_INLINE_VISIBILITY + bool valid() const _NOEXCEPT {return __state_ != nullptr;} + + _LIBCPP_INLINE_VISIBILITY + void wait() const {__state_->wait();} + template <class _Rep, class _Period> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const + {return __state_->wait_for(__rel_time);} + template <class _Clock, class _Duration> + _LIBCPP_INLINE_VISIBILITY + future_status + wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const + {return __state_->wait_until(__abs_time);} +}; + +template <class _Rp> +inline _LIBCPP_INLINE_VISIBILITY +void +swap(shared_future<_Rp>& __x, shared_future<_Rp>& __y) _NOEXCEPT +{ + __x.swap(__y); +} + +template <class _Rp> +inline +shared_future<_Rp> +future<_Rp>::share() _NOEXCEPT +{ + return shared_future<_Rp>(_VSTD::move(*this)); +} + +template <class _Rp> +inline +shared_future<_Rp&> +future<_Rp&>::share() _NOEXCEPT +{ + return shared_future<_Rp&>(_VSTD::move(*this)); +} + +inline +shared_future<void> +future<void>::share() _NOEXCEPT +{ + return shared_future<void>(_VSTD::move(*this)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !_LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP_FUTURE |