25 std::chrono::steady_clock::duration interval_;
26 boost::asio::strand<typename Context::executor_type> strand_;
28 enum class State { Running, Stopped };
29 std::atomic<State> state_ = State::Stopped;
31 std::binary_semaphore semaphore_{0};
32 boost::asio::steady_timer timer_;
35 RepeatedTask(std::chrono::steady_clock::duration interval, Context& ctx)
36 : interval_(interval), strand_(boost::asio::make_strand(ctx)), timer_(strand_)
45 template <
typename Fn>
46 requires std::invocable<Fn, boost::asio::yield_context> or std::invocable<Fn>
50 ASSERT(state_ == State::Stopped,
"Can only be ran once");
51 state_ = State::Running;
52 util::spawn(strand_, [
this, f = std::forward<Fn>(f)](boost::asio::yield_context yield) {
53 boost::system::error_code ec;
55 while (state_ == State::Running) {
56 timer_.expires_after(interval_);
57 timer_.async_wait(yield[ec]);
59 if (ec or state_ != State::Running)
62 if constexpr (std::invocable<
decltype(f), boost::asio::yield_context>) {
76 if (
auto expected = State::Running;
77 not state_.compare_exchange_strong(expected, State::Stopped))
80 std::binary_semaphore cancelSemaphore{0};
81 boost::asio::post(strand_, [
this, &cancelSemaphore]() {
83 cancelSemaphore.release();
85 cancelSemaphore.acquire();