mrs_lib
Various reusable classes, functions and utilities for use in MRS projects
Loading...
Searching...
No Matches
continuation.hpp
1#ifndef MRS_LIB_CORO_INTERNAL_CONTINUATION_HPP_
2#define MRS_LIB_CORO_INTERNAL_CONTINUATION_HPP_
3
4
5#include <coroutine>
6#include <functional>
7#include <stop_token>
8#include <utility>
9
10namespace mrs_lib::coro::internal
11{
12
21 template <typename T>
22 std::coroutine_handle<T> coroutine_handle_reinterpret_cast(std::coroutine_handle<> handle)
23 {
24 return std::coroutine_handle<T>::from_address(handle.address());
25 }
26
36 template <typename T>
38
39 template <>
41 {
42 };
43
54 {
55 private:
56 template <typename T>
57 using ContinuationGetterFptr = CancellableContinuation (*)(std::coroutine_handle<T>);
58 template <typename T>
59 using TokenGetterFptr = std::stop_token (*)(std::coroutine_handle<T>);
60
61 public:
66
70 explicit CancellableContinuation(std::coroutine_handle<void>) = delete;
71
77 template <typename T>
78 explicit CancellableContinuation(std::coroutine_handle<T> handle)
79 : data_{
80 .func = [](std::coroutine_handle<> handle) -> CancellableContinuation {
81 using Trait = CancellableContinuationFor<T>;
82 static_assert(std::same_as<decltype(&Trait::release_continuation), ContinuationGetterFptr<T>>,
83 "Wrong signature for CancellableContinuationFor<T>::release_continuation.");
84 static_assert(std::same_as<decltype(&Trait::get_token), TokenGetterFptr<T>>, "Wrong signature for CancellableContinuationFor<T>::get_token.");
85 return Trait::release_continuation(coroutine_handle_reinterpret_cast<T>(handle));
86 },
87 .handle = handle,
88 .stop_token = CancellableContinuationFor<T>::get_token(coroutine_handle_reinterpret_cast<T>(handle)),
89 }
90 {
91 }
92
97 {
98 cancel_and_destroy();
99 }
100
102 CancellableContinuation& operator=(const CancellableContinuation&) = delete;
103 CancellableContinuation(CancellableContinuation&& other) noexcept : data_(std::exchange(other.data_, {}))
104 {
105 }
106 CancellableContinuation& operator=(CancellableContinuation&& other) noexcept
107 {
108 std::ranges::swap(data_, other.data_);
109 return *this;
110 }
111
117 std::coroutine_handle<> release()
118 {
119 return std::exchange(data_.handle, nullptr);
120 }
121
128 {
129 ContinuationData local_data = release_data();
130
131 while (local_data.handle != nullptr)
132 {
133 CancellableContinuation continuation = std::invoke(local_data.func, local_data.handle);
134 local_data.handle.destroy();
135 local_data = continuation.release_data();
136 }
137 }
138
142 std::stop_token get_token() const
143 {
144 return data_.stop_token;
145 }
146
150 friend bool operator==(const CancellableContinuation& continuation, std::nullptr_t)
151 {
152 return continuation.data_.handle == nullptr;
153 }
154
155 private:
159 struct ContinuationData
160 {
161 ContinuationGetterFptr<void> func = nullptr;
162 std::coroutine_handle<> handle = nullptr;
163 std::stop_token stop_token{};
164 };
165
169 ContinuationData release_data()
170 {
171 return std::exchange(data_, {});
172 }
173
174 ContinuationData data_;
175 };
176
177} // namespace mrs_lib::coro::internal
178
179#endif // MRS_LIB_CORO_INTERNAL_CONTINUATION_HPP_
Owning coroutine handle supporting cancellation.
Definition continuation.hpp:54
void cancel_and_destroy()
Cancel the stored continuation, if there is any.
Definition continuation.hpp:127
CancellableContinuation(std::coroutine_handle< T > handle)
Construct continuation that will own the passed handle.
Definition continuation.hpp:78
CancellableContinuation()=default
Construct empty continuation.
std::stop_token get_token() const
Get stop token associated with the continuation.
Definition continuation.hpp:142
friend bool operator==(const CancellableContinuation &continuation, std::nullptr_t)
Check if the current continuation is empty.
Definition continuation.hpp:150
std::coroutine_handle release()
Release ownership of the stored handle, giving it to the caller.
Definition continuation.hpp:117
CancellableContinuation(std::coroutine_handle< void >)=delete
Cancellable continuation cannot be constructed from type erased handle.
~CancellableContinuation()
Destroy stored continuation if there is any.
Definition continuation.hpp:96
Type trait to obtain data necessary for creating CancellableContinuation.
Definition continuation.hpp:37