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:
68 using cancellable_yield_context_type = boost::asio::
69 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 =
79 boost::signals2::signal<void(boost::asio::cancellation_type_t)>;
80 std::shared_ptr<FamilyCancellationSignal> familySignal_;
81 boost::signals2::connection connection_;
82
89 explicit Coroutine(
90 boost::asio::yield_context&& yield,
91 std::shared_ptr<FamilyCancellationSignal> signal =
92 std::make_shared<FamilyCancellationSignal>()
93 );
94
95public:
100 ~Coroutine();
101
102 Coroutine(Coroutine const&) = delete;
103 Coroutine(Coroutine&&) = delete;
104
105 Coroutine&
106 operator==(Coroutine&&) = delete;
107
108 Coroutine&
109 operator==(Coroutine const&) = delete;
110
120 template <typename ExecutionContext, CoroutineFunction Fn>
121 static void
122 spawnNew(ExecutionContext& ioContext, Fn fn)
123 {
124 util::spawn(ioContext, [fn = std::move(fn)](boost::asio::yield_context yield) {
125 Coroutine thisCoroutine{std::move(yield)};
126 fn(thisCoroutine);
127 });
128 }
129
137 template <CoroutineFunction Fn>
138 void
140 {
141 if (isCancelled_)
142 return;
143
145 yield_,
146 [signal = familySignal_, fn = std::move(fn)](boost::asio::yield_context yield) mutable {
147 Coroutine coroutine(std::move(yield), std::move(signal));
148 fn(coroutine);
149 }
150 );
151 }
152
157 [[nodiscard]] boost::system::error_code
158 error() const;
159
165 void
166 cancelAll(
167 boost::asio::cancellation_type_t cancellationType = boost::asio::cancellation_type::terminal
168 );
169
174 [[nodiscard]] bool
175 isCancelled() const;
176
184 yieldContext() const;
185
190 [[nodiscard]] boost::asio::any_io_executor
191 executor() const;
192
197 void
198 yield() const;
199};
200
201} // 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:122
~Coroutine()
Destructor for the Coroutine. Handles cleanup, such as disconnecting from the cancellation signal.
Definition Coroutine.cpp:50
boost::system::error_code error() const
Returns the error code, if any, associated with the last operation in this coroutine.
Definition Coroutine.cpp:56
bool isCancelled() const
Checks if this coroutine has been cancelled.
Definition Coroutine.cpp:70
boost::asio::any_io_executor executor() const
Returns the executor associated with this coroutine's yield context.
Definition Coroutine.cpp:82
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:62
void spawnChild(Fn fn)
Spawns a child coroutine from this coroutine. The child coroutine shares the same cancellation signal...
Definition Coroutine.hpp:139
cancellable_yield_context_type yieldContext() const
Returns the cancellable yield context associated with this coroutine. This context should be used for...
Definition Coroutine.cpp:76
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
void yield() const
Explicitly yields execution back to the scheduler. This can be used to allow other tasks to run.
Definition Coroutine.cpp:88
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:72