Clio develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
Strand.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/async/Concepts.hpp"
23#include "util/async/context/impl/Cancellation.hpp"
24#include "util/async/context/impl/Execution.hpp"
25#include "util/async/context/impl/Timer.hpp"
26#include "util/async/context/impl/Utils.hpp"
27#include "util/async/impl/ErrorHandling.hpp"
28
29#include <chrono>
30#include <functional>
31#include <optional>
32#include <type_traits>
33
34namespace util::async::impl {
35
36template <
37 typename ParentContextType,
38 typename StopSourceType,
39 typename DispatcherType,
40 typename TimerContextProvider = impl::SelfContextProvider,
41 typename ErrorHandlerType = impl::DefaultErrorHandler>
43 std::reference_wrapper<ParentContextType> parentContext_;
44 typename ParentContextType::ContextHolderType::Strand context_;
46
47public:
48 static constexpr bool kIS_NOEXCEPT = noexcept(ErrorHandlerType::wrap([](auto&) { throw 0; }));
49
50 using ContextHolderType = typename ParentContextType::ContextHolderType::Strand;
51 using ExecutorType = typename ContextHolderType::Executor;
52 using StopToken = typename StopSourceType::Token;
53 using Timer =
54 typename ParentContextType::ContextHolderType::Timer; // timers are associated with the parent context
55
56 BasicStrand(ParentContextType& parent, auto&& strand)
57 : parentContext_{std::ref(parent)}, context_{std::forward<decltype(strand)>(strand)}
58 {
59 }
60
61 ~BasicStrand() = default;
62 BasicStrand(BasicStrand&&) = default;
63
64 BasicStrand(BasicStrand const&) = delete;
65
66 [[nodiscard]] auto
67 execute(SomeHandlerWith<StopToken> auto&& fn, std::optional<std::chrono::milliseconds> timeout = std::nullopt) const
68 noexcept(kIS_NOEXCEPT)
69 {
70 return DispatcherType::dispatch(
71 context_,
72 impl::outcomeForHandler<StopSourceType>(fn),
73 ErrorHandlerType::wrap([this, timeout, fn = std::forward<decltype(fn)>(fn)](
74 auto& outcome, auto& stopSource, auto stopToken
75 ) mutable {
76 [[maybe_unused]] auto timeoutHandler = impl::getTimeoutHandleIfNeeded(
77 TimerContextProvider::getContext(parentContext_.get()), timeout, stopSource
78 );
79
80 using FnRetType = std::decay_t<decltype(fn(std::declval<StopToken>()))>;
81 if constexpr (std::is_void_v<FnRetType>) {
82 fn(std::move(stopToken));
83 outcome.setValue();
84 } else {
85 outcome.setValue(fn(std::move(stopToken)));
86 }
87 })
88 );
89 }
90
91 [[nodiscard]] auto
92 execute(SomeHandlerWith<StopToken> auto&& fn, SomeStdDuration auto timeout) const noexcept(kIS_NOEXCEPT)
93 {
94 return execute(
95 std::forward<decltype(fn)>(fn),
96 std::make_optional(std::chrono::duration_cast<std::chrono::milliseconds>(timeout))
97 );
98 }
99
100 [[nodiscard]] auto
101 execute(SomeHandlerWithoutStopToken auto&& fn) const noexcept(kIS_NOEXCEPT)
102 {
103 return DispatcherType::dispatch(
104 context_,
105 impl::outcomeForHandler<StopSourceType>(fn),
106 ErrorHandlerType::wrap([fn = std::forward<decltype(fn)>(fn)](auto& outcome) mutable {
107 using FnRetType = std::decay_t<decltype(fn())>;
108 if constexpr (std::is_void_v<FnRetType>) {
109 fn();
110 outcome.setValue();
111 } else {
112 outcome.setValue(fn());
113 }
114 })
115 );
116 }
117};
118
119} // namespace util::async::impl
Definition Strand.hpp:42
Specifies the interface for a handler that can be invoked with the specified args.
Definition Concepts.hpp:154
Specifies the interface for a handler that can be stopped.
Definition Concepts.hpp:146
Specifies that the type must be some std::duration.
Definition Concepts.hpp:162