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_) {
118 }
119 coroutine_.destroy();
120 }
121 }
122
123 void except(const std::exception_ptr &exc) { slot = exc; }
124
126 std::optional<std::variant<T, std::exception_ptr>> slot;
127
128protected:
131 std::coroutine_handle<> coroutine_;
134 std::coroutine_handle<> waitingHandle_;
135 static_assert(sizeof(std::coroutine_handle<>) <= sizeof(void *),
136 "coroutine_handle is unusually large");
138};
139
146template <> class PromiseCore<void> {
147public:
148 PromiseCore() = default;
149 PromiseCore(const PromiseCore &) = delete;
150 PromiseCore(PromiseCore &&) = delete;
151 PromiseCore<void> &operator=(const PromiseCore &) = delete;
153 ~PromiseCore() = default;
154
156 void setHandle(std::coroutine_handle<> handle);
157
159 void resetHandle();
161 [[nodiscard]] bool isAwaited() const;
163 [[nodiscard]] bool ready() const;
165 [[nodiscard]] bool stale() const;
166
168 void resume();
169
171 void except(std::exception_ptr exc);
172
173 // Managing coroutine state.
174 void setRunning(std::coroutine_handle<> handle);
175
176 // Destroy the coroutine state associated with this core. Must be routinely
177 // invoked after coroutine completion (due to suspend_always returned from
178 // final_suspend).
179 void destroyCoroutine();
180
183 bool ready_ = false;
184
186 std::optional<std::exception_ptr> exception_;
187
188private:
189 std::coroutine_handle<> coroutine_;
190 std::coroutine_handle<> waitingHandle_;
192};
193
195
196} // 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:131
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:137
void except(const std::exception_ptr &exc)
Definition promise_core.h:123
PromiseCore(T &&value)
Definition promise_core.h:54
void resume()
Definition promise_core.h:100
std::coroutine_handle waitingHandle_
Definition promise_core.h:134
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:126
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