uvco 0.1
Loading...
Searching...
No Matches
promise_core.h
Go to the documentation of this file.
1// uvco (c) 2023 Lewin Bormann. See LICENSE for specific terms.
2
3#pragma once
4
5#include "uvco/exception.h"
6#include "uvco/loop/loop.h"
7
8#include <boost/assert.hpp>
9#include <fmt/core.h>
10#include <fmt/format.h>
11
12#include <coroutine>
13#include <exception>
14#include <optional>
15#include <utility>
16#include <uv.h>
17#include <variant>
18
19namespace uvco {
22
31enum class PromiseState {
34 init = 0,
41};
42
45template <typename T> class PromiseCore {
46public:
47 PromiseCore() = default;
48 PromiseCore(const PromiseCore &) = delete;
50 PromiseCore &operator=(const PromiseCore &) = delete;
52 virtual ~PromiseCore() = default;
53
54 explicit PromiseCore(T &&value)
55 : slot{std::move(value)}, state_{PromiseState::finished} {}
56
58 virtual void setHandle(std::coroutine_handle<> handle) {
60 throw UvcoException("PromiseCore is already awaited or has finished");
61 }
62 waitingHandle_ = handle;
64 }
65
67 void setRunning(std::coroutine_handle<> handle) {
68 BOOST_ASSERT(state_ == PromiseState::init);
69 coroutine_ = handle;
70 }
71
83
85 bool isAwaited() { return waitingHandle_ != nullptr; }
86
88 [[nodiscard]] bool ready() const { return slot.has_value(); }
89
92 [[nodiscard]] bool stale() const {
93 return state_ == PromiseState::finished && !ready();
94 }
95
100 void resume() {
101 if (waitingHandle_) {
102 BOOST_ASSERT(state_ == PromiseState::waitedOn);
103 const std::coroutine_handle<> resume = waitingHandle_;
104 waitingHandle_ = nullptr;
106 } else {
107 // This occurs if no co_await has occured until resume. Either the
108 // promise was not co_awaited, or the producing coroutine immediately
109 // returned a value. (await_ready() == true)
110 }
112 }
113
115 if (coroutine_) {
117 coroutine_.destroy();
118 }
119 }
120
121 void except(const std::exception_ptr &exc) { slot = exc; }
122
124 std::optional<std::variant<T, std::exception_ptr>> slot;
125
126protected:
129 std::coroutine_handle<> coroutine_;
132 std::coroutine_handle<> waitingHandle_;
133 static_assert(sizeof(std::coroutine_handle<>) <= sizeof(void *),
134 "coroutine_handle is unusually large");
136};
137
144template <> class PromiseCore<void> {
145public:
146 PromiseCore() = default;
147 PromiseCore(const PromiseCore &) = delete;
148 PromiseCore(PromiseCore &&) = delete;
149 PromiseCore<void> &operator=(const PromiseCore &) = delete;
151 ~PromiseCore() = default;
152
154 void setHandle(std::coroutine_handle<> handle);
155
157 void resetHandle();
159 [[nodiscard]] bool isAwaited() const;
161 [[nodiscard]] bool ready() const;
163 [[nodiscard]] bool stale() const;
164
166 void resume();
167
169 void except(std::exception_ptr exc);
170
171 // Managing coroutine state.
172 void setRunning(std::coroutine_handle<> handle);
173
174 // Destroy the coroutine state associated with this core. Must be routinely
175 // invoked after coroutine completion (due to suspend_always returned from
176 // final_suspend).
177 void destroyCoroutine() {
178 if (coroutine_) {
180 coroutine_.destroy();
181 }
182 }
183
186 bool ready_ = false;
187
189 std::optional<std::exception_ptr> exception_;
190
191private:
192 std::coroutine_handle<> coroutine_;
193 std::coroutine_handle<> waitingHandle_;
195};
196
198
199} // namespace uvco
static void cancel(std::coroutine_handle<> handle)
Definition loop.cc:104
static void enqueue(std::coroutine_handle<> handle)
Definition loop.cc:94
Definition promise_core.h:45
void destroyCoroutine()
Definition promise_core.h:114
PromiseCore(const PromiseCore &)=delete
std::coroutine_handle coroutine_
Definition promise_core.h:129
bool ready() const
Checks if a value is present in the slot.
Definition promise_core.h:88
virtual ~PromiseCore()=default
bool stale() const
Definition promise_core.h:92
PromiseCore()=default
PromiseState state_
Definition promise_core.h:135
void except(const std::exception_ptr &exc)
Definition promise_core.h:121
PromiseCore(T &&value)
Definition promise_core.h:54
void resume()
Definition promise_core.h:100
std::coroutine_handle waitingHandle_
Definition promise_core.h:132
virtual void setHandle(std::coroutine_handle<> handle)
Set the coroutine to be resumed once a result is ready.
Definition promise_core.h:58
bool isAwaited()
Checks if a coroutine is waiting on a promise belonging to this core.
Definition promise_core.h:85
void resetHandle()
Definition promise_core.h:74
std::optional< std::variant< T, std::exception_ptr > > slot
The slot contains the result once obtained.
Definition promise_core.h:124
PromiseCore & operator=(PromiseCore &&)=delete
void setRunning(std::coroutine_handle<> handle)
Used by Coroutine<T> to set the producing coroutine handle.
Definition promise_core.h:67
PromiseCore & operator=(const PromiseCore &)=delete
PromiseCore(PromiseCore &&)=delete
PromiseState
Definition promise_core.h:31
@ waitedOn
Definition promise_core.h:37
@ finished
Definition promise_core.h:40
@ init
Definition promise_core.h:34
Definition async_work.cc:18
Definition exception.h:19