59 lines
1.8 KiB
C++
59 lines
1.8 KiB
C++
#include "timer.hpp"
|
|
#include "spdlog/spdlog.h"
|
|
|
|
#include <boost/asio/any_io_executor.hpp>
|
|
#include <boost/asio/co_spawn.hpp>
|
|
#include <boost/asio/detached.hpp>
|
|
#include <boost/asio/steady_timer.hpp>
|
|
#include <boost/asio/use_awaitable.hpp>
|
|
#include <chrono>
|
|
#include <functional>
|
|
#include <memory>
|
|
|
|
namespace ranczo {
|
|
struct PeriodicTimer::Impl {
|
|
private:
|
|
std::chrono::milliseconds _interval;
|
|
boost::asio::steady_timer _timer;
|
|
std::function< void() > _callback;
|
|
|
|
public:
|
|
Impl(boost::asio::any_io_executor & io_context, std::chrono::milliseconds interval, std::function< void() > cb)
|
|
: _interval{interval}, _timer(io_context, _interval), _callback{std::move(cb)} {
|
|
start();
|
|
}
|
|
|
|
// Coroutine function to handle the timer expiration
|
|
boost::asio::awaitable< void > timerCoroutine() {
|
|
assert(_callback);
|
|
|
|
try {
|
|
while(true) {
|
|
// call my callback
|
|
_callback();
|
|
|
|
// Wait for the timer to expire
|
|
co_await _timer.async_wait(boost::asio::use_awaitable);
|
|
|
|
// Reset the timer for the next interval
|
|
_timer.expires_after(_interval);
|
|
}
|
|
} catch(const std::exception & e) {
|
|
spdlog::error("Error: {}", e.what());
|
|
}
|
|
}
|
|
|
|
void start() {
|
|
spdlog::trace("co_spawn timer");
|
|
// Start the coroutine by invoking the timerCoroutine() with boost::asio::co_spawn
|
|
boost::asio::co_spawn(_timer.get_executor(), timerCoroutine(), boost::asio::detached);
|
|
}
|
|
};
|
|
|
|
PeriodicTimer::PeriodicTimer(executor & executor, std::chrono::milliseconds period, std::function< void() > cb)
|
|
: _impl{std::make_unique< Impl >(executor, period, std::move(cb))} {}
|
|
|
|
PeriodicTimer::~PeriodicTimer() = default;
|
|
|
|
} // namespace ranczo
|