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
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;
47
49 operator=(ErasedOperation const&) = delete;
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
74private:
75 struct Concept {
76 virtual ~Concept() = default;
77
78 virtual void
79 wait() noexcept = 0;
80 virtual std::expected<std::any, ExecutionError>
81 get() = 0;
82 virtual void
83 abort() = 0;
84 };
85
86 template <SomeOperation OpType>
87 struct Model : Concept {
88 OpType operation;
89
90 template <typename OType>
91 requires std::is_same_v<OType, OpType>
92 Model(OType&& operation) : operation{std::forward<OType>(operation)}
93 {
94 }
95
96 void
97 wait() noexcept override
98 {
99 if constexpr (not SomeAwaitable<OpType>) {
100 ASSERT(false, "Called wait() on an operation that does not support it");
101 std::unreachable();
102 } else {
103 operation.wait();
104 }
105 }
106
107 std::expected<std::any, ExecutionError>
108 get() override
109 {
110 if constexpr (not SomeOperationWithData<OpType>) {
111 ASSERT(false, "Called get() on an operation that does not support it");
112 std::unreachable();
113 } else {
114 // Note: return type of the operation was already wrapped to std::any by AnyExecutionContext
115 return operation.get();
116 }
117 }
118
119 void
120 abort() override
121 {
122 if constexpr (not SomeCancellableOperation<OpType> and not SomeStoppableOperation<OpType> and
123 not SomeAbortable<OpType>) {
124 ASSERT(false, "Called abort() on an operation that can't be aborted, cancelled nor stopped");
125 } else {
126 if constexpr (SomeAbortable<OpType>) {
127 operation.abort();
128 } else {
129 if constexpr (SomeCancellableOperation<OpType>)
130 operation.cancel();
131 if constexpr (SomeStoppableOperation<OpType>)
132 operation.requestStop();
133 }
134 }
135 }
136 };
137
138private:
139 std::unique_ptr<Concept> pimpl_;
140};
141
142} // namespace util::async::impl
Definition ErasedOperation.hpp:34
void abort()
Cancel if needed and request stop as soon as possible.
Definition ErasedOperation.hpp:69
Specifies the interface for an operation that can be awaited.
Definition Concepts.hpp:52
Specifies the interface for an operation.
Definition Concepts.hpp:68
Error channel type for async operation of any ExecutionContext.
Definition Error.hpp:39