Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
ErasedOperation.hpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of clio: https://github.com/XRPLF/clio
4 Copyright (c) 2024, 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/Assert.hpp"
23#include "util/async/Concepts.hpp"
24#include "util/async/Error.hpp"
25
26#include <any>
27#include <expected>
28#include <memory>
29#include <type_traits>
30#include <utility>
31
32namespace util::async::impl {
33
34class ErasedOperation {
35public:
36 template <SomeOperation OpType>
37 requires(not std::is_same_v<std::decay_t<OpType>, ErasedOperation>)
38 /* implicit */ ErasedOperation(OpType&& operation)
39 : pimpl_{std::make_unique<Model<OpType>>(std::forward<OpType>(operation))}
40 {
41 }
42
43 ~ErasedOperation() = default;
44
45 ErasedOperation(ErasedOperation const&) = delete;
46 ErasedOperation(ErasedOperation&&) = default;
47
48 ErasedOperation&
49 operator=(ErasedOperation const&) = delete;
50 ErasedOperation&
51 operator=(ErasedOperation&&) = default;
52
53 void
54 wait() noexcept
55 {
56 pimpl_->wait();
57 }
58
59 std::expected<std::any, ExecutionError>
60 get()
61 {
62 return pimpl_->get();
63 }
64
68 void
70 {
71 pimpl_->abort();
72 }
73
74 void
75 invoke()
76 {
77 pimpl_->invoke();
78 }
79
80private:
81 struct Concept {
82 virtual ~Concept() = default;
83
84 virtual void
85 wait() noexcept = 0;
86 virtual std::expected<std::any, ExecutionError>
87 get() = 0;
88 virtual void
89 abort() = 0;
90 virtual void
91 invoke() = 0;
92 };
93
94 template <SomeOperation OpType>
95 struct Model : Concept {
96 OpType operation;
97
98 template <typename OType>
99 requires std::is_same_v<OType, OpType>
100 Model(OType&& operation) : operation{std::forward<OType>(operation)}
101 {
102 }
103
104 void
105 wait() noexcept override
106 {
107 if constexpr (not SomeAwaitable<OpType>) {
108 ASSERT(false, "Called wait() on an operation that does not support it");
109 std::unreachable();
110 } else {
111 operation.wait();
112 }
113 }
114
115 std::expected<std::any, ExecutionError>
116 get() override
117 {
118 if constexpr (not SomeOperationWithData<OpType>) {
119 ASSERT(false, "Called get() on an operation that does not support it");
120 std::unreachable();
121 } else {
122 // Note: return type of the operation was already wrapped to std::any by
123 // AnyExecutionContext
124 return operation.get();
125 }
126 }
127
128 void
129 abort() override
130 {
131 if constexpr (not SomeCancellableOperation<OpType> and
132 not SomeStoppableOperation<OpType> and not SomeAbortable<OpType>) {
133 ASSERT(
134 false,
135 "Called abort() on an operation that can't be aborted, cancelled nor stopped"
136 );
137 } else {
138 if constexpr (SomeAbortable<OpType>) {
139 operation.abort();
140 } else {
141 if constexpr (SomeCancellableOperation<OpType>)
142 operation.cancel();
143 if constexpr (SomeStoppableOperation<OpType>)
144 operation.requestStop();
145 }
146 }
147 }
148
149 void
150 invoke() override
151 {
152 if constexpr (not SomeForceInvocableOperation<OpType>) {
153 ASSERT(false, "Called invoke() on an operation that can't be force-invoked");
154 } else {
155 operation.invoke();
156 }
157 }
158 };
159
160private:
161 std::unique_ptr<Concept> pimpl_;
162};
163
164} // namespace util::async::impl
void abort()
Cancel if needed and request stop as soon as possible.
Definition ErasedOperation.hpp:69
Specifies the interface for an operation.
Definition Concepts.hpp:90
Error channel type for async operation of any ExecutionContext.
Definition Error.hpp:39