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 <boost/asio/any_io_executor.hpp>
23#include <boost/asio/bind_cancellation_slot.hpp>
24#include <boost/asio/cancellation_signal.hpp>
25#include <boost/asio/cancellation_type.hpp>
26#include <boost/asio/error.hpp>
27#include <boost/asio/spawn.hpp>
28#include <boost/signals2/connection.hpp>
29#include <boost/signals2/signal.hpp>
30#include <boost/signals2/variadic_signal.hpp>
31
32#include <atomic>
33#include <concepts>
34#include <csignal>
35#include <cstddef>
36#include <memory>
37#include <utility>
38
39namespace util {
40
41class Coroutine;
42
48template <typename Fn>
49concept CoroutineFunction = std::invocable<Fn, Coroutine&> and not std::is_reference_v<Fn>;
50
60class Coroutine {
61public:
67 boost::asio::cancellation_slot_binder<boost::asio::yield_context, boost::asio::cancellation_slot>;
68
69private:
70 boost::asio::yield_context yield_;
71 boost::system::error_code error_;
72 boost::asio::cancellation_signal cancellationSignal_;
74 std::atomic_bool isCancelled_{false};
75
76 using FamilyCancellationSignal = boost::signals2::signal<void(boost::asio::cancellation_type_t)>;
77 std::shared_ptr<FamilyCancellationSignal> familySignal_;
78 boost::signals2::connection connection_;
79
85 explicit Coroutine(
86 boost::asio::yield_context&& yield,
87 std::shared_ptr<FamilyCancellationSignal> signal = std::make_shared<FamilyCancellationSignal>()
88 );
89
90public:
95 ~Coroutine();
96
97 Coroutine(Coroutine const&) = delete;
98 Coroutine(Coroutine&&) = delete;
99
100 Coroutine&
101 operator==(Coroutine&&) = delete;
102
103 Coroutine&
104 operator==(Coroutine const&) = delete;
105
113 template <typename ExecutionContext, CoroutineFunction Fn>
114 static void
115 spawnNew(ExecutionContext& ioContext, Fn fn)
116 {
117 boost::asio::spawn(ioContext, [fn = std::move(fn)](boost::asio::yield_context yield) {
118 Coroutine thisCoroutine{std::move(yield)};
119 fn(thisCoroutine);
120 });
121 }
122
129 template <CoroutineFunction Fn>
130 void
132 {
133 if (isCancelled_)
134 return;
135
136 boost::asio::spawn(
137 yield_,
138 [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 }
144
149 [[nodiscard]] boost::system::error_code
150 error() const;
151
157 void
158 cancelAll(boost::asio::cancellation_type_t cancellationType = boost::asio::cancellation_type::terminal);
159
164 [[nodiscard]] bool
165 isCancelled() const;
166
174 yieldContext() const;
175
180 [[nodiscard]] boost::asio::any_io_executor
181 executor() const;
182
187 void
188 yield() const;
189};
190
191} // namespace util
Manages a coroutine execution context, allowing for cooperative multitasking and cancellation.
Definition Coroutine.hpp:60
static void spawnNew(ExecutionContext &ioContext, Fn fn)
Spawns a new top-level coroutine.
Definition Coroutine.hpp:115
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:66
~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:131
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:49
This namespace contains various utilities.
Definition AccountUtils.hpp:30