45 std::chrono::steady_clock::duration interval_;
46 boost::asio::strand<typename Context::executor_type> strand_;
48 enum class State { Running, Stopped };
49 std::atomic<State> state_ = State::Stopped;
51 std::binary_semaphore semaphore_{0};
52 boost::asio::steady_timer timer_;
55 RepeatedTask(std::chrono::steady_clock::duration interval, Context& ctx)
56 : interval_(interval), strand_(boost::asio::make_strand(ctx)), timer_(strand_)
65 template <
typename Fn>
66 requires std::invocable<Fn, boost::asio::yield_context> or std::invocable<Fn>
70 ASSERT(state_ == State::Stopped,
"Can only be ran once");
71 state_ = State::Running;
72 util::spawn(strand_, [
this, f = std::forward<Fn>(f)](boost::asio::yield_context yield) {
73 boost::system::error_code ec;
75 while (state_ == State::Running) {
76 timer_.expires_after(interval_);
77 timer_.async_wait(yield[ec]);
79 if (ec or state_ != State::Running)
82 if constexpr (std::invocable<
decltype(f), boost::asio::yield_context>) {
96 if (
auto expected = State::Running; not state_.compare_exchange_strong(expected, State::Stopped))
99 boost::asio::spawn(strand_, [
this](
auto&&) { timer_.cancel(); }, boost::asio::use_future).wait();
100 semaphore_.acquire();