#include "config.hpp" #include 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