Clio develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
Coroutine.hpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of clio: https://github.com/XRPLF/clio
4 Copyright (c) 2025, the clio developers.
5
6 Permission to use, copy, modify, and distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#pragma once
21
22#include "util/Spawn.hpp"
23
24#include <boost/asio/any_io_executor.hpp>
25#include <boost/asio/bind_cancellation_slot.hpp>
26#include <boost/asio/cancellation_signal.hpp>
27#include <boost/asio/cancellation_type.hpp>
28#include <boost/asio/error.hpp>
29#include <boost/asio/spawn.hpp>
30#include <boost/signals2/connection.hpp>
31#include <boost/signals2/signal.hpp>
32#include <boost/signals2/variadic_signal.hpp>
33
34#include <atomic>
35#include <concepts>
36#include <csignal>
37#include <cstddef>
38#include <memory>
39#include <utility>
40
41namespace util {
42
43class Coroutine;
44
50template <typename Fn>
51concept CoroutineFunction = std::invocable<Fn, Coroutine&> and not std::is_reference_v<Fn>;
52
62class Coroutine {
63public:
69 boost::asio::cancellation_slot_binder<boost::asio::yield_context, boost::asio::cancellation_slot>;
70
71private:
72 boost::asio::yield_context yield_;
73 boost::system::error_code error_;
74 boost::asio::cancellation_signal cancellationSignal_;
76 std::atomic_bool isCancelled_{false};
77
78 using FamilyCancellationSignal = boost::signals2::signal<void(boost::asio::cancellation_type_t)>;
79 std::shared_ptr<FamilyCancellationSignal> familySignal_;
80 boost::signals2::connection connection_;
81
87 explicit Coroutine(
88 boost::asio::yield_context&& yield,
89 std::shared_ptr<FamilyCancellationSignal> signal = std::make_shared<FamilyCancellationSignal>()
90 );
91
92public:
97 ~Coroutine();
98
99 Coroutine(Coroutine const&) = delete;
100 Coroutine(Coroutine&&) = delete;
101
102 Coroutine&
103 operator==(Coroutine&&) = delete;
104
105 Coroutine&
106 operator==(Coroutine const&) = delete;
107
115 template <typename ExecutionContext, CoroutineFunction Fn>
116 static void
117 spawnNew(ExecutionContext& ioContext, Fn fn)
118 {
119 util::spawn(ioContext, [fn = std::move(fn)](boost::asio::yield_context yield) {
120 Coroutine thisCoroutine{std::move(yield)};
121 fn(thisCoroutine);
122 });
123 }
124
131 template <CoroutineFunction Fn>
132 void
134 {
135 if (isCancelled_)
136 return;
137
138 util::spawn(yield_, [signal = familySignal_, fn = std::move(fn)](boost::asio::yield_context yield) mutable {
139 Coroutine coroutine(std::move(yield), std::move(signal));
140 fn(coroutine);
141 });
142 }
143
148 [[nodiscard]] boost::system::error_code
149 error() const;
150
156 void
157 cancelAll(boost::asio::cancellation_type_t cancellationType = boost::asio::cancellation_type::terminal);
158
163 [[nodiscard]] bool
164 isCancelled() const;
165
173 yieldContext() const;
174
179 [[nodiscard]] boost::asio::any_io_executor
180 executor() const;
181
186 void
187 yield() const;
188};
189
190} // namespace util
Manages a coroutine execution context, allowing for cooperative multitasking and cancellation.
Definition Coroutine.hpp:62
static void spawnNew(ExecutionContext &ioContext, Fn fn)
Spawns a new top-level coroutine.
Definition Coroutine.hpp:117
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:68
~Coroutine()
Destructor for the Coroutine. Handles cleanup, such as disconnecting from the cancellation signal.
Definition Coroutine.cpp:47
boost::system::error_code error() const
Returns the error code, if any, associated with the last operation in this coroutine.
Definition Coroutine.cpp:53
bool isCancelled() const
Checks if this coroutine has been cancelled.
Definition Coroutine.cpp:67
boost::asio::any_io_executor executor() const
Returns the executor associated with this coroutine's yield context.
Definition Coroutine.cpp:79
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:59
void spawnChild(Fn fn)
Spawns a child coroutine from this coroutine. The child coroutine shares the same cancellation signal...
Definition Coroutine.hpp:133
cancellable_yield_context_type yieldContext() const
Returns the cancellable yield context associated with this coroutine. This context should be used for...
Definition Coroutine.cpp:73
void yield() const
Explicitly yields execution back to the scheduler. This can be used to allow other tasks to run.
Definition Coroutine.cpp:85
Concept for functions that can be used as coroutine bodies. Such functions must be invocable with a C...
Definition Coroutine.hpp:51
This namespace contains various utilities.
Definition AccountUtils.hpp:30
void spawn(Ctx &&ctx, F &&func)
Spawns a coroutine using boost::asio::spawn
Definition Spawn.hpp:69