Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
Coroutine.hpp
1#pragma once
2
3#include "util/Spawn.hpp"
4
5#include <boost/asio/any_io_executor.hpp>
6#include <boost/asio/bind_cancellation_slot.hpp>
7#include <boost/asio/cancellation_signal.hpp>
8#include <boost/asio/cancellation_type.hpp>
9#include <boost/asio/error.hpp>
10#include <boost/asio/spawn.hpp>
11#include <boost/signals2/connection.hpp>
12#include <boost/signals2/signal.hpp>
13#include <boost/signals2/variadic_signal.hpp>
14
15#include <atomic>
16#include <concepts>
17#include <csignal>
18#include <cstddef>
19#include <memory>
20#include <utility>
21
22namespace util {
23
24class Coroutine;
25
31template <typename Fn>
32concept CoroutineFunction = std::invocable<Fn, Coroutine&> and not std::is_reference_v<Fn>;
33
43class Coroutine {
44public:
49 using cancellable_yield_context_type = boost::asio::
50 cancellation_slot_binder<boost::asio::yield_context, boost::asio::cancellation_slot>;
51
52private:
53 boost::asio::yield_context yield_;
54 boost::system::error_code error_;
55 boost::asio::cancellation_signal cancellationSignal_;
57 std::atomic_bool isCancelled_{false};
58
59 using FamilyCancellationSignal =
60 boost::signals2::signal<void(boost::asio::cancellation_type_t)>;
61 std::shared_ptr<FamilyCancellationSignal> familySignal_;
62 boost::signals2::connection connection_;
63
70 explicit Coroutine(
71 boost::asio::yield_context&& yield,
72 std::shared_ptr<FamilyCancellationSignal> signal =
73 std::make_shared<FamilyCancellationSignal>()
74 );
75
76public:
81 ~Coroutine();
82
83 Coroutine(Coroutine const&) = delete;
84 Coroutine(Coroutine&&) = delete;
85
87 operator==(Coroutine&&) = delete;
88
90 operator==(Coroutine const&) = delete;
91
101 template <typename ExecutionContext, CoroutineFunction Fn>
102 static void
103 spawnNew(ExecutionContext& ioContext, Fn fn)
104 {
105 util::spawn(ioContext, [fn = std::move(fn)](boost::asio::yield_context yield) {
106 Coroutine thisCoroutine{std::move(yield)};
107 fn(thisCoroutine);
108 });
109 }
110
118 template <CoroutineFunction Fn>
119 void
121 {
122 if (isCancelled_)
123 return;
124
126 yield_,
127 [signal = familySignal_, fn = std::move(fn)](boost::asio::yield_context yield) mutable {
128 Coroutine coroutine(std::move(yield), std::move(signal));
129 fn(coroutine);
130 }
131 );
132 }
133
138 [[nodiscard]] boost::system::error_code
139 error() const;
140
146 void
147 cancelAll(
148 boost::asio::cancellation_type_t cancellationType = boost::asio::cancellation_type::terminal
149 );
150
155 [[nodiscard]] bool
156 isCancelled() const;
157
165 yieldContext() const;
166
171 [[nodiscard]] boost::asio::any_io_executor
172 executor() const;
173
178 void
179 yield() const;
180};
181
182} // namespace util
Manages a coroutine execution context, allowing for cooperative multitasking and cancellation.
Definition Coroutine.hpp:43
static void spawnNew(ExecutionContext &ioContext, Fn fn)
Spawns a new top-level coroutine.
Definition Coroutine.hpp:103
~Coroutine()
Destructor for the Coroutine. Handles cleanup, such as disconnecting from the cancellation signal.
Definition Coroutine.cpp:31
boost::system::error_code error() const
Returns the error code, if any, associated with the last operation in this coroutine.
Definition Coroutine.cpp:37
bool isCancelled() const
Checks if this coroutine has been cancelled.
Definition Coroutine.cpp:51
boost::asio::any_io_executor executor() const
Returns the executor associated with this coroutine's yield context.
Definition Coroutine.cpp:63
void cancelAll(boost::asio::cancellation_type_t cancellationType=boost::asio::cancellation_type::terminal)
Cancels all coroutines sharing the same root cancellation signal.
Definition Coroutine.cpp:43
void spawnChild(Fn fn)
Spawns a child coroutine from this coroutine. The child coroutine shares the same cancellation signal...
Definition Coroutine.hpp:120
cancellable_yield_context_type yieldContext() const
Returns the cancellable yield context associated with this coroutine. This context should be used for...
Definition Coroutine.cpp:57
boost::asio:: cancellation_slot_binder< boost::asio::yield_context, boost::asio::cancellation_slot > cancellable_yield_context_type
Type alias for a yield_context that is bound to a cancellation slot. This allows asynchronous operati...
Definition Coroutine.hpp:49
void yield() const
Explicitly yields execution back to the scheduler. This can be used to allow other tasks to run.
Definition Coroutine.cpp:69
Concept for functions that can be used as coroutine bodies. Such functions must be invocable with a C...
Definition Coroutine.hpp:32
This namespace contains various utilities.
Definition AccountUtils.hpp:11
void spawn(Ctx &&ctx, F &&func)
Spawns a coroutine using boost::asio::spawn.
Definition Spawn.hpp:53