#pragma once #if __cplusplus < 201103L #error "C++ version lower than C++11" #endif #include #include #include #include #include namespace std { enum class future_status { ready, timeout, deferred }; namespace detail { class shared_state_base { protected: typedef void (*deleter_fn)(void *v); using scoped_lock = std::lock_guard; using unique_lock = std::unique_lock; public: explicit shared_state_base(deleter_fn d) : v_(nullptr), d_(d), valid_(true) {} ~shared_state_base() { d_(v_); } shared_state_base(shared_state_base &&other) = delete; shared_state_base(const shared_state_base &other) = delete; shared_state_base &operator=(shared_state_base &&other) = delete; shared_state_base &operator=(const shared_state_base &other) = delete; void wait() { unique_lock lock(m_); c_.wait(lock, [this] { return has_value(); }); } template std::future_status wait_for(const std::chrono::duration &rel_time) { unique_lock lock(m_); if (c_.wait_for(lock, rel_time, [this] { return has_value(); })) { return std::future_status::ready; } return std::future_status::timeout; } template std::future_status wait_until(const std::chrono::time_point &abs_time) { unique_lock lock(m_); if (c_.wait_until(lock, abs_time, [this] { return has_value(); })) { return std::future_status::ready; } return std::future_status::timeout; } protected: bool has_value() { return v_ != nullptr; } protected: std::mutex m_; std::condition_variable c_; void *v_; deleter_fn d_; bool valid_; }; template class shared_state: public shared_state_base { public: shared_state() :shared_state_base(default_deleter_) {} ~shared_state() {} R &get() { wait(); scoped_lock lock(m_); assert(valid_); valid_ = false; return *(static_cast(v_)); } void set(const R &v) { scoped_lock lock(m_); assert(!has_value()); v_ = new R(v); valid_ = true; c_.notify_one(); } void set(R &&v) { scoped_lock lock(m_); assert(!has_value()); v_ = new R(std::move(v)); valid_ = true; c_.notify_one(); } bool valid() { scoped_lock lock(m_); return valid_; } private: static void default_deleter_(void *v) { delete static_cast(v); } }; } // namespace detail template class shared_future { }; template class future { using state_type = std::shared_ptr>; public: future() {} explicit future(const state_type &state) : state_(state) {} future(future &&other) noexcept: state_(std::move(other.state_)) { other.state_.reset(); } future(const future &other) = delete; ~future() {} future &operator=(future &&other) noexcept { if (&other != this) { state_ = std::move(other.state_); other.state_.reset(); } return *this; } future &operator=(const future &other) = delete; void swap(future &other) noexcept { std::swap(state_, other.state_); } std::shared_future share() noexcept { return std::shared_future(); } R get() { return state_->get(); } bool valid() const noexcept { return state_->valid(); } void wait() const { state_->wait(); } template std::future_status wait_for(const std::chrono::duration &rel_time) const { return state_->wait_for(rel_time); } template std::future_status wait_until(const std::chrono::time_point &abs_time) const { return state_->wait_until(abs_time); } private: state_type state_; }; template <> class future { using state_type = std::shared_ptr>; public: future() {} explicit future(const state_type &state) : state_(state) {} future(future &&other) noexcept: state_(std::move(other.state_)) { other.state_.reset(); } future(const future &other) = delete; ~future() {} future &operator=(future &&other) noexcept { if (&other != this) { state_ = std::move(other.state_); other.state_.reset(); } return *this; } future &operator=(const future &other) = delete; void swap(future &other) noexcept { std::swap(state_, other.state_); } std::shared_future share() noexcept { return std::shared_future(); } void get() { state_->get(); } bool valid() const noexcept { return state_->valid(); } void wait() const { state_->wait(); } template std::future_status wait_for(const std::chrono::duration &rel_time) const { return state_->wait_for(rel_time); } template std::future_status wait_until(const std::chrono::time_point &abs_time) const { return state_->wait_until(abs_time); } private: state_type state_; }; template class promise { using state_type = std::shared_ptr>; public: promise() : state_(new detail::shared_state()) {} promise(promise &&other) noexcept: state_(std::move(other.state_)) { other.state_.reset(); } promise(const promise &other) = delete; ~promise() {} promise &operator=(promise &&other) noexcept { if (&other != this) { state_ = std::move(other.state_); other.state_.reset(); } return *this; } promise &operator=(const promise &other) = delete; void swap(promise &other) noexcept { std::swap(state_, other.state_); } std::future get_future() { return std::future(state_); } void set_value(const R &value) { state_->set(value); } void set_value(R &&value) { state_->set(std::move(value)); } void set_value_at_thread_exit(const R &value); void set_value_at_thread_exit(R &&value); void set_exception(std::exception_ptr p); void set_exception_at_thread_exit(std::exception_ptr p); private: state_type state_; }; template <> class promise { using state_type = std::shared_ptr>; public: promise() : state_(new detail::shared_state()) {} promise(promise &&other) noexcept: state_(std::move(other.state_)) { other.state_.reset(); } promise(const promise &other) = delete; ~promise() {} promise &operator=(promise &&other) noexcept { if (&other != this) { state_ = std::move(other.state_); other.state_.reset(); } return *this; } promise &operator=(const promise &other) = delete; void swap(promise &other) noexcept { std::swap(state_, other.state_); } std::future get_future() { return std::future(state_); } void set_value() { state_->set(0); } void set_value_at_thread_exit(); void set_exception(std::exception_ptr p); void set_exception_at_thread_exit(std::exception_ptr p); private: state_type state_; }; template void swap(std::future &lhs, std::future &rhs) noexcept { lhs.swap(rhs); } template void swap(std::promise &lhs, std::promise &rhs) noexcept { lhs.swap(rhs); } } // namespace std