Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
Repeat.hpp
1#pragma once
2
3#include "util/Assert.hpp"
4
5#include <boost/asio/any_io_executor.hpp>
6#include <boost/asio/io_context.hpp>
7#include <boost/asio/post.hpp>
8#include <boost/asio/steady_timer.hpp>
9#include <boost/asio/strand.hpp>
10
11#include <atomic>
12#include <chrono>
13#include <concepts>
14#include <memory>
15#include <semaphore>
16#include <utility>
17
18namespace util {
19
25class Repeat {
26 struct Control {
27 boost::asio::steady_timer timer;
28 boost::asio::strand<boost::asio::any_io_executor> strand;
29 std::atomic_bool stopping{true};
30 std::binary_semaphore semaphore{0};
31
32 Control(auto& ctx) : timer(ctx), strand(boost::asio::make_strand(ctx))
33 {
34 }
35 };
36
37 std::shared_ptr<Control> control_;
38
39public:
47 Repeat(auto& ctx) : control_(std::make_unique<Control>(ctx))
48 {
49 }
50
51 Repeat(Repeat const&) = delete;
52 Repeat&
53 operator=(Repeat const&) = delete;
54 Repeat(Repeat&&) = default;
55 Repeat&
56 operator=(Repeat&&) = default;
57
63 void
64 stop();
65
74 template <std::invocable Action>
75 void
76 start(std::chrono::steady_clock::duration interval, Action&& action)
77 {
78 ASSERT(control_->stopping, "Should be stopped before starting");
79 control_->stopping = false;
80 startImpl(control_, interval, std::forward<Action>(action));
81 }
82
83private:
84 template <std::invocable Action>
85 static void
86 startImpl(
87 std::shared_ptr<Control> control,
88 std::chrono::steady_clock::duration interval,
89 Action&& action
90 )
91 {
92 boost::asio::post(
93 control->strand, [control, interval, action = std::forward<Action>(action)]() mutable {
94 if (control->stopping) {
95 control->semaphore.release();
96 return;
97 }
98
99 control->timer.expires_after(interval);
100 control->timer.async_wait(
101 [control,
102 interval,
103 action = std::forward<Action>(action)](auto const& ec) mutable {
104 if (ec or control->stopping) {
105 control->semaphore.release();
106 return;
107 }
108 action();
109
110 startImpl(std::move(control), interval, std::forward<Action>(action));
111 }
112 );
113 }
114 );
115 }
116};
117
118} // namespace util
A class to repeat some action at a regular interval.
Definition Repeat.hpp:25
void stop()
Stop repeating.
Definition Repeat.cpp:8
void start(std::chrono::steady_clock::duration interval, Action &&action)
Start asynchronously repeating.
Definition Repeat.hpp:76
Repeat(auto &ctx)
Construct a new Repeat object.
Definition Repeat.hpp:47
This namespace contains various utilities.
Definition AccountUtils.hpp:11