From ecf989901f089fcf277e475a7b85aa980a657a55 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 18 Aug 2014 00:23:34 +0300 Subject: [PATCH] future specialization --- reactor.hh | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/reactor.hh b/reactor.hh index b3b5db3e91..f9d2ffbc00 100644 --- a/reactor.hh +++ b/reactor.hh @@ -159,6 +159,68 @@ struct future_state { } }; +template <> +struct future_state { + promise* _promise = nullptr; + future* _future = nullptr; + std::unique_ptr _task; + enum class state { + invalid, + future, + result, + exception, + } _state = state::future; + union any { + any() {} + ~any() {} + std::exception_ptr ex; + } _u; + ~future_state() noexcept { + switch (_state) { + case state::future: + break; + case state::result: + break; + case state::exception: + _u.ex.~exception_ptr(); + break; + default: + abort(); + } + } + bool available() const { return _state == state::result || _state == state::exception; } + bool has_promise() const { return _promise; } + bool has_future() const { return _future; } + void wait(); + void make_ready(); + void set() { + assert(_state == state::future); + _state = state::result; + make_ready(); + } + void set_exception(std::exception_ptr ex) { + assert(_state == state::future); + _state = state::exception; + new (&_u.ex) std::exception_ptr(ex); + make_ready(); + } + void get() { + while (_state == state::future) { + abort(); + } + if (_state == state::exception) { + std::rethrow_exception(_u.ex); + } + } + template + void schedule(Func&& func) { + _task = make_task(std::forward(func)); + if (available()) { + make_ready(); + } + } +}; + template class promise { future_state* _state; @@ -181,6 +243,27 @@ public: void set_value(T&& result) { _state->set(std::move(result)); } }; +template <> +class promise { + future_state* _state; +public: + promise() : _state(new future_state()) { _state->_promise = this; } + promise(promise&& x) : _state(std::move(x._state)) { x._state = nullptr; } + promise(const promise&) = delete; + ~promise() { + if (_state) { + _state->_promise = nullptr; + if (!_state->has_future()) { + delete _state; + } + } + } + promise& operator=(promise&&); + void operator=(const promise&) = delete; + future get_future(); + void set_value() { _state->set(); } +}; + template struct is_future : std::false_type {}; template struct is_future> : std::true_type {}; @@ -244,6 +327,69 @@ public: friend class promise; }; +template <> +class future { + future_state* _state; +private: + future(future_state* state) : _state(state) { _state->_future = this; } +public: + using value_type = void; + future(future&& x) : _state(x._state) { x._state = nullptr; } + future(const future&) = delete; + future& operator=(future&& x); + void operator=(const future&) = delete; + ~future() { + if (_state) { + _state->_future = nullptr; + if (!_state->has_promise()) { + delete _state; + } + } + } + void get() { + } + + template + void then(Func, Enable); + + template + void then(Func&& func, + std::enable_if_t, void>::value, void*> = nullptr) { + auto state = _state; + if (state->available()) { + _state->get(); + return func(); + } + state->schedule([fut = std::move(*this), func = std::forward(func)] () mutable { + fut.get(); + func(); + }); + } + + template + std::result_of_t + then(Func&& func, + std::enable_if_t>::value, void*> = nullptr) { + auto state = _state; + if (state->available()) { + _state->get(); + return func(); + } + using U = typename std::result_of_t::value_type; + promise pr; + auto next_fut = pr.get_future(); + state->schedule([fut = std::move(*this), func = std::forward(func), pr = std::move(pr)] () mutable { + fut.get(); + func().then([pr = std::move(pr)] (U next) mutable { + pr.set_value(std::move(next)); + }); + }); + return std::move(next_fut); + } + + friend class promise; +}; + template inline future