ranczo-io/libs/asio_watchdog.cpp
Bartosz Wieczorek 2db84fb720 checkpoint
2025-11-06 13:31:21 +01:00

93 lines
2.7 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "config.hpp"
#include <ranczo-io/utils/asio_watchdog.hpp>
namespace ranczo {
SoftWatchdog::SoftWatchdog(boost::asio::any_io_executor ex, Dur period, AlarmFn alarm, bool periodic_alarm)
: strand_(boost::asio::make_strand(ex)), timer_(strand_), period_(period), alarm_(std::move(alarm)), periodic_alarm_(periodic_alarm) {}
void SoftWatchdog::start() {
boost::asio::dispatch(strand_, [this] {
if(active_)
return;
active_ = true;
last_touch_ = Clock::now(); // zaczynamy liczyć od teraz
arm_from_now_(); // uzbrój timer
});
}
void SoftWatchdog::stop() {
boost::asio::dispatch(strand_, [this] {
active_ = false;
timer_.cancel();
});
}
void SoftWatchdog::touch() { // alias: kick()
boost::asio::dispatch(strand_, [this] {
if(!active_)
return;
last_touch_ = Clock::now();
timer_.cancel(); // handler rozpozna cancel i uzbroi timer od nowa
});
}
void SoftWatchdog::arm_from_now_() {
timer_.expires_after(period_);
timer_.async_wait(boost::asio::bind_executor(strand_, [this](const boost::system::error_code & ec) { on_timer_(ec); }));
}
void SoftWatchdog::set_period(Dur d) {
boost::asio::dispatch(strand_, [this, d] {
period_ = d;
timer_.cancel();
});
}
void SoftWatchdog::on_timer_(const boost::system::error_code & ec) {
if(!active_)
return;
if(ec == boost::asio::error::operation_aborted) {
// Został wykonany touch() / set_period() / stop(); ustaw ponownie
if(active_)
arm_from_now_();
return;
}
if(ec) {
// Inny błąd — uzbrój ponownie „na wszelki wypadek”
if(active_)
arm_from_now_();
return;
}
// Timer naturalnie wygasł sprawdź, czy rzeczywiście NIKT nie dotknął
auto now = Clock::now();
auto since_touch = now - last_touch_;
if(since_touch >= period_) {
// faktycznie timeout bez touch()
try {
if(alarm_)
alarm_();
} catch(...) {
}
if(!periodic_alarm_) {
// Tryb one-shot: czekamy na następne touch() (nie uzbrajamy automatycznie)
return;
}
// Tryb periodyczny: jeśli nadal brak touch(), chcemy bić co „period_”
// Ustawiamy nowy okres od teraz; kolejne alarmy będą co „period_”
if(active_)
arm_from_now_();
} else {
// ktoś dotknął tuż przed wygaśnięciem; przeliczymy okres od teraz
if(active_)
arm_from_now_();
}
}
// bool SoftWatchdog::is_armed() const noexcept {
// return active_.load(std::memory_order_relaxed);
// }
} // namespace ranczo