123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- //===------------------------- future.cpp ---------------------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is dual licensed under the MIT and the University of Illinois Open
- // Source Licenses. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- #include "__config"
- #ifndef _LIBCPP_HAS_NO_THREADS
- #include "future"
- #include "string"
- _LIBCPP_BEGIN_NAMESPACE_STD
- class _LIBCPP_HIDDEN __future_error_category
- : public __do_message
- {
- public:
- virtual const char* name() const _NOEXCEPT;
- virtual string message(int ev) const;
- };
- const char*
- __future_error_category::name() const _NOEXCEPT
- {
- return "future";
- }
- #if defined(__clang__)
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wswitch"
- #elif defined(__GNUC__) || defined(__GNUG__)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wswitch"
- #endif
- string
- __future_error_category::message(int ev) const
- {
- switch (static_cast<future_errc>(ev))
- {
- case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)
- case future_errc::broken_promise:
- return string("The associated promise has been destructed prior "
- "to the associated state becoming ready.");
- case future_errc::future_already_retrieved:
- return string("The future has already been retrieved from "
- "the promise or packaged_task.");
- case future_errc::promise_already_satisfied:
- return string("The state of the promise has already been set.");
- case future_errc::no_state:
- return string("Operation not permitted on an object without "
- "an associated state.");
- }
- return string("unspecified future_errc value\n");
- }
- #if defined(__clang__)
- #pragma clang diagnostic pop
- #elif defined(__GNUC__) || defined(__GNUG__)
- #pragma GCC diagnostic pop
- #endif
- const error_category&
- future_category() _NOEXCEPT
- {
- static __future_error_category __f;
- return __f;
- }
- future_error::future_error(error_code __ec)
- : logic_error(__ec.message()),
- __ec_(__ec)
- {
- }
- future_error::~future_error() _NOEXCEPT
- {
- }
- void
- __assoc_sub_state::__on_zero_shared() _NOEXCEPT
- {
- delete this;
- }
- void
- __assoc_sub_state::set_value()
- {
- unique_lock<mutex> __lk(__mut_);
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__has_value())
- throw future_error(make_error_code(future_errc::promise_already_satisfied));
- #endif
- __state_ |= __constructed | ready;
- __cv_.notify_all();
- }
- void
- __assoc_sub_state::set_value_at_thread_exit()
- {
- unique_lock<mutex> __lk(__mut_);
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__has_value())
- throw future_error(make_error_code(future_errc::promise_already_satisfied));
- #endif
- __state_ |= __constructed;
- __thread_local_data()->__make_ready_at_thread_exit(this);
- }
- void
- __assoc_sub_state::set_exception(exception_ptr __p)
- {
- unique_lock<mutex> __lk(__mut_);
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__has_value())
- throw future_error(make_error_code(future_errc::promise_already_satisfied));
- #endif
- __exception_ = __p;
- __state_ |= ready;
- __cv_.notify_all();
- }
- void
- __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
- {
- unique_lock<mutex> __lk(__mut_);
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__has_value())
- throw future_error(make_error_code(future_errc::promise_already_satisfied));
- #endif
- __exception_ = __p;
- __thread_local_data()->__make_ready_at_thread_exit(this);
- }
- void
- __assoc_sub_state::__make_ready()
- {
- unique_lock<mutex> __lk(__mut_);
- __state_ |= ready;
- __cv_.notify_all();
- }
- void
- __assoc_sub_state::copy()
- {
- unique_lock<mutex> __lk(__mut_);
- __sub_wait(__lk);
- if (__exception_ != nullptr)
- rethrow_exception(__exception_);
- }
- void
- __assoc_sub_state::wait()
- {
- unique_lock<mutex> __lk(__mut_);
- __sub_wait(__lk);
- }
- void
- __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
- {
- if (!__is_ready())
- {
- if (__state_ & static_cast<unsigned>(deferred))
- {
- __state_ &= ~static_cast<unsigned>(deferred);
- __lk.unlock();
- __execute();
- }
- else
- while (!__is_ready())
- __cv_.wait(__lk);
- }
- }
- void
- __assoc_sub_state::__execute()
- {
- #ifndef _LIBCPP_NO_EXCEPTIONS
- throw future_error(make_error_code(future_errc::no_state));
- #endif
- }
- future<void>::future(__assoc_sub_state* __state)
- : __state_(__state)
- {
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__state_->__has_future_attached())
- throw future_error(make_error_code(future_errc::future_already_retrieved));
- #endif
- __state_->__add_shared();
- __state_->__set_future_attached();
- }
- future<void>::~future()
- {
- if (__state_)
- __state_->__release_shared();
- }
- void
- future<void>::get()
- {
- unique_ptr<__shared_count, __release_shared_count> __(__state_);
- __assoc_sub_state* __s = __state_;
- __state_ = nullptr;
- __s->copy();
- }
- promise<void>::promise()
- : __state_(new __assoc_sub_state)
- {
- }
- promise<void>::~promise()
- {
- if (__state_)
- {
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (!__state_->__has_value() && __state_->use_count() > 1)
- __state_->set_exception(make_exception_ptr(
- future_error(make_error_code(future_errc::broken_promise))
- ));
- #endif // _LIBCPP_NO_EXCEPTIONS
- __state_->__release_shared();
- }
- }
- future<void>
- promise<void>::get_future()
- {
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__state_ == nullptr)
- throw future_error(make_error_code(future_errc::no_state));
- #endif
- return future<void>(__state_);
- }
- void
- promise<void>::set_value()
- {
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__state_ == nullptr)
- throw future_error(make_error_code(future_errc::no_state));
- #endif
- __state_->set_value();
- }
- void
- promise<void>::set_exception(exception_ptr __p)
- {
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__state_ == nullptr)
- throw future_error(make_error_code(future_errc::no_state));
- #endif
- __state_->set_exception(__p);
- }
- void
- promise<void>::set_value_at_thread_exit()
- {
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__state_ == nullptr)
- throw future_error(make_error_code(future_errc::no_state));
- #endif
- __state_->set_value_at_thread_exit();
- }
- void
- promise<void>::set_exception_at_thread_exit(exception_ptr __p)
- {
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (__state_ == nullptr)
- throw future_error(make_error_code(future_errc::no_state));
- #endif
- __state_->set_exception_at_thread_exit(__p);
- }
- shared_future<void>::~shared_future()
- {
- if (__state_)
- __state_->__release_shared();
- }
- shared_future<void>&
- shared_future<void>::operator=(const shared_future& __rhs)
- {
- if (__rhs.__state_)
- __rhs.__state_->__add_shared();
- if (__state_)
- __state_->__release_shared();
- __state_ = __rhs.__state_;
- return *this;
- }
- _LIBCPP_END_NAMESPACE_STD
- #endif // !_LIBCPP_HAS_NO_THREADS
|