123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- #pragma once
- #if __cplusplus < 201103L
- #error "C++ version lower than C++11"
- #endif
- #include <mutex>
- #include <condition_variable>
- #include <memory>
- #include <chrono>
- #include <cassert>
- 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<std::mutex>;
- using unique_lock = std::unique_lock<std::mutex>;
- 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 <class Rep, class Period>
- std::future_status
- wait_for(const std::chrono::duration<Rep, Period> &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 <class Clock, class Duration>
- std::future_status
- wait_until(const std::chrono::time_point<Clock, Duration> &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 <typename R>
- 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<R *>(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<R *>(v); }
- };
- } // namespace detail
- template <typename R>
- class shared_future {
- };
- template <typename R>
- class future {
- using state_type = std::shared_ptr<detail::shared_state<R>>;
- 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<R> share() noexcept { return std::shared_future<R>(); }
- R get() { return state_->get(); }
- bool valid() const noexcept { return state_->valid(); }
- void wait() const { state_->wait(); }
- template <class Rep, class Period>
- std::future_status
- wait_for(const std::chrono::duration<Rep, Period> &rel_time) const {
- return state_->wait_for(rel_time);
- }
- template <class Clock, class Duration>
- std::future_status
- wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) const {
- return state_->wait_until(abs_time);
- }
- private:
- state_type state_;
- };
- template <>
- class future<void> {
- using state_type = std::shared_ptr<detail::shared_state<int>>;
- 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<void> share() noexcept { return std::shared_future<void>(); }
- void get() { state_->get(); }
- bool valid() const noexcept { return state_->valid(); }
- void wait() const { state_->wait(); }
- template <class Rep, class Period>
- std::future_status
- wait_for(const std::chrono::duration<Rep, Period> &rel_time) const {
- return state_->wait_for(rel_time);
- }
- template <class Clock, class Duration>
- std::future_status
- wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) const {
- return state_->wait_until(abs_time);
- }
- private:
- state_type state_;
- };
- template <typename R>
- class promise {
- using state_type = std::shared_ptr<detail::shared_state<R>>;
- public:
- promise() : state_(new detail::shared_state<R>()) {}
- 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<R> get_future() { return std::future<R>(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<void> {
- using state_type = std::shared_ptr<detail::shared_state<int>>;
- public:
- promise() : state_(new detail::shared_state<int>()) {}
- 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<void> get_future() { return std::future<void>(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 <class R>
- void swap(std::future<R> &lhs, std::future<R> &rhs) noexcept {
- lhs.swap(rhs);
- }
- template <class R>
- void swap(std::promise<R> &lhs, std::promise<R> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace std
|