Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
AnyStrand.hpp
1#pragma once
2
3#include "util/async/AnyOperation.hpp"
4#include "util/async/AnyStopToken.hpp"
5#include "util/async/Concepts.hpp"
6#include "util/async/impl/ErasedOperation.hpp"
7
8#include <any>
9#include <chrono>
10#include <functional>
11#include <memory>
12#include <optional>
13#include <type_traits>
14#include <utility>
15
16namespace util::async {
17
21class AnyStrand {
22public:
29 template <NotSameAs<AnyStrand> StrandType>
30 /* implicit */ AnyStrand(StrandType&& strand)
31 : pimpl_{std::make_shared<Model<StrandType>>(std::forward<StrandType>(strand))}
32 {
33 }
34
35 AnyStrand(AnyStrand const&) = default;
36 AnyStrand(AnyStrand&&) = default;
37 ~AnyStrand() = default;
38
45 [[nodiscard]] auto
47 {
48 using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
49 static_assert(not std::is_same_v<RetType, std::any>);
50
51 return AnyOperation<RetType>( //
52 pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
53 if constexpr (std::is_void_v<RetType>) {
54 std::invoke(std::forward<decltype(fn)>(fn));
55 return {};
56 } else {
57 return std::make_any<RetType>(std::invoke(std::forward<decltype(fn)>(fn)));
58 }
59 })
60 );
61 }
62
69 [[nodiscard]] auto
71 {
72 using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
73 static_assert(not std::is_same_v<RetType, std::any>);
74
75 return AnyOperation<RetType>( //
76 pimpl_->execute(
77 [fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
78 if constexpr (std::is_void_v<RetType>) {
79 std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
80 return {};
81 } else {
82 return std::make_any<RetType>(
83 std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken))
84 );
85 }
86 }
87 )
88 );
89 }
90
98 [[nodiscard]] auto
100 {
101 using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
102 static_assert(not std::is_same_v<RetType, std::any>);
103
104 return AnyOperation<RetType>( //
105 pimpl_->execute(
106 [fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
107 if constexpr (std::is_void_v<RetType>) {
108 std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
109 return {};
110 } else {
111 return std::make_any<RetType>(
112 std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken))
113 );
114 }
115 },
116 std::chrono::duration_cast<std::chrono::milliseconds>(timeout)
117 )
118 );
119 }
120
128 [[nodiscard]] auto
130 {
131 using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
132 static_assert(not std::is_same_v<RetType, std::any>);
133
134 auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(interval);
135 return AnyOperation<RetType>( //
136 pimpl_->executeRepeatedly(
137 millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
138 std::invoke(std::forward<decltype(fn)>(fn));
139 return {};
140 }
141 )
142 );
143 }
144
151 void
153 {
154 pimpl_->submit(std::forward<decltype(fn)>(fn));
155 }
156
157private:
158 struct Concept {
159 virtual ~Concept() = default;
160
161 [[nodiscard]] virtual impl::ErasedOperation
162 execute(
163 std::function<std::any(AnyStopToken)>,
164 std::optional<std::chrono::milliseconds> timeout = std::nullopt
165 ) = 0;
166 [[nodiscard]] virtual impl::ErasedOperation execute(std::function<std::any()>) = 0;
167 [[nodiscard]] virtual impl::ErasedOperation
168 executeRepeatedly(std::chrono::milliseconds, std::function<std::any()>) = 0;
169 virtual void submit(std::function<void()>) = 0;
170 };
171
172 template <typename StrandType>
173 struct Model : Concept {
174 StrandType strand;
175
176 template <typename SType>
177 requires std::is_same_v<SType, StrandType>
178 Model(SType&& strand) : strand{std::forward<SType>(strand)}
179 {
180 }
181
182 [[nodiscard]] impl::ErasedOperation
183 execute(
184 std::function<std::any(AnyStopToken)> fn,
185 std::optional<std::chrono::milliseconds> timeout
186 ) override
187 {
188 return strand.execute(std::move(fn), timeout);
189 }
190
191 [[nodiscard]] impl::ErasedOperation
192 execute(std::function<std::any()> fn) override
193 {
194 return strand.execute(std::move(fn));
195 }
196
197 impl::ErasedOperation
198 executeRepeatedly(std::chrono::milliseconds interval, std::function<std::any()> fn) override
199 {
200 return strand.executeRepeatedly(interval, std::move(fn));
201 }
202
203 void
204 submit(std::function<void()> fn) override
205 {
206 return strand.submit(std::move(fn));
207 }
208 };
209
210private:
211 std::shared_ptr<Concept> pimpl_;
212};
213
214} // namespace util::async
A type-erased operation that can be executed via AnyExecutionContext.
Definition AnyOperation.hpp:25
A type-erased stop token.
Definition AnyStopToken.hpp:18
A type-erased execution context.
Definition AnyStrand.hpp:21
auto executeRepeatedly(SomeStdDuration auto interval, SomeHandlerWithoutStopToken auto &&fn)
Schedule a repeating operation on the execution context.
Definition AnyStrand.hpp:129
void submit(SomeHandlerWithoutStopToken auto &&fn)
Schedule an operation on the execution context without expectations of a result.
Definition AnyStrand.hpp:152
AnyStrand(StrandType &&strand)
Construct a new Any Strand object.
Definition AnyStrand.hpp:30
auto execute(SomeHandlerWithoutStopToken auto &&fn)
Execute a function without a stop token on the strand.
Definition AnyStrand.hpp:46
auto execute(SomeHandlerWith< AnyStopToken > auto &&fn)
Execute a function taking a stop token on the strand.
Definition AnyStrand.hpp:70
auto execute(SomeHandlerWith< AnyStopToken > auto &&fn, SomeStdDuration auto timeout)
Execute a function taking a stop token on the strand with a timeout.
Definition AnyStrand.hpp:99
Definition ErasedOperation.hpp:15
Specifies the interface for a handler that can be invoked with the specified args.
Definition Concepts.hpp:165
Specifies the interface for a handler that can be stopped.
Definition Concepts.hpp:157
Specifies that the type must be some std::duration.
Definition Concepts.hpp:173
This namespace implements an async framework built on top of execution contexts.
Definition AnyExecutionContext.hpp:17