From d8f28ec8a2faabad3aabb9f7a26755971424ef05 Mon Sep 17 00:00:00 2001 From: theraven Date: Tue, 22 Nov 2011 17:30:41 +0000 Subject: Import libcxxrt / libc++ into a vendor branch. Approved by: dim (mentor) --- src/future.cpp | 285 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 src/future.cpp (limited to 'src/future.cpp') diff --git a/src/future.cpp b/src/future.cpp new file mode 100644 index 0000000..ff59110 --- /dev/null +++ b/src/future.cpp @@ -0,0 +1,285 @@ +//===------------------------- 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 "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"; +} + +string +__future_error_category::message(int ev) const +{ + switch (ev) + { + 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"); +} + +const error_category& +future_category() +{ + 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 __lk(__mut_); +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__has_value()) + throw future_error(make_error_code(future_errc::promise_already_satisfied)); +#endif + __state_ |= __constructed | ready; + __lk.unlock(); + __cv_.notify_all(); +} + +void +__assoc_sub_state::set_value_at_thread_exit() +{ + unique_lock __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); + __lk.unlock(); +} + +void +__assoc_sub_state::set_exception(exception_ptr __p) +{ + unique_lock __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; + __lk.unlock(); + __cv_.notify_all(); +} + +void +__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) +{ + unique_lock __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); + __lk.unlock(); +} + +void +__assoc_sub_state::__make_ready() +{ + unique_lock __lk(__mut_); + __state_ |= ready; + __lk.unlock(); + __cv_.notify_all(); +} + +void +__assoc_sub_state::copy() +{ + unique_lock __lk(__mut_); + __sub_wait(__lk); + if (__exception_ != nullptr) + rethrow_exception(__exception_); +} + +void +__assoc_sub_state::wait() +{ + unique_lock __lk(__mut_); + __sub_wait(__lk); +} + +void +__assoc_sub_state::__sub_wait(unique_lock& __lk) +{ + if (!__is_ready()) + { + if (__state_ & deferred) + { + __state_ &= ~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::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::~future() +{ + if (__state_) + __state_->__release_shared(); +} + +void +future::get() +{ + unique_ptr<__shared_count, __release_shared_count> __(__state_); + __assoc_sub_state* __s = __state_; + __state_ = nullptr; + __s->copy(); +} + +promise::promise() + : __state_(new __assoc_sub_state) +{ +} + +promise::~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(); + } +} + +future +promise::get_future() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__state_ == nullptr) + throw future_error(make_error_code(future_errc::no_state)); +#endif + return future(__state_); +} + +void +promise::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::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::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::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::~shared_future() +{ + if (__state_) + __state_->__release_shared(); +} + +shared_future& +shared_future::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 -- cgit v1.1