LCOV - code coverage report
Current view: top level - asio - watchdog.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 35 35
Test Date: 2026-11-10 10:38:07 Functions: 100.0 % 8 8

            Line data    Source code
       1              : #include "watchdog.hpp"
       2              : #include <algorithm>
       3              : 
       4              : namespace thinger::asio {
       5              : 
       6        32622 : watchdog::watchdog(boost::asio::any_io_executor executor, std::function<void()> on_expired)
       7        32622 :     : state_(std::make_shared<state>(boost::asio::steady_timer{std::move(executor)}, std::move(on_expired))) {}
       8              : 
       9        32622 : watchdog::~watchdog() {
      10        32622 :     cancel();
      11        32622 : }
      12              : 
      13       324429 : void watchdog::expires_at(clock::time_point time) {
      14       324429 :     state_->deadline = time;
      15              :     // A running timer checks the new deadline when it expires, unless it is earlier
      16       324429 :     if (!state_->armed || std::max(state_->deadline, state_->hold) < state_->timer.expiry()) arm(state_);
      17       324429 : }
      18              : 
      19           12 : void watchdog::hold_until(clock::time_point time) {
      20              :     // A running timer checks the hold when it expires
      21           12 :     state_->hold = std::max(state_->hold, time);
      22           12 : }
      23              : 
      24        73178 : void watchdog::cancel() {
      25        73178 :     state_->armed = false;
      26        73178 :     state_->timer.cancel();
      27        73178 : }
      28              : 
      29        35773 : void watchdog::arm(const std::shared_ptr<state>& s) {
      30        35773 :     s->armed = true;
      31              :     // Re-arming cancels the wait in progress, whose handler then returns
      32        35773 :     s->timer.expires_at(std::max(s->deadline, s->hold));
      33        35773 :     s->timer.async_wait([weak = std::weak_ptr<state>(s)](const boost::system::error_code& ec) {
      34        30996 :         on_timer(weak, ec);
      35        30996 :     });
      36        35773 : }
      37              : 
      38        30996 : void watchdog::on_timer(const std::weak_ptr<state>& weak, const boost::system::error_code& ec) {
      39        31622 :     if (ec) return;  // cancelled or re-armed
      40         5598 :     auto s = weak.lock();
      41         5598 :     if (!s || !s->armed) return;  // gone, or cancelled once the timer had expired
      42         5588 :     auto now = clock::now();
      43              :     // The timer was set again after this wait had expired: the wait of the new expiry checks
      44         5588 :     if (now < s->timer.expiry()) return;
      45              :     // Some activity moved the deadline meanwhile, or a hold keeps it
      46         5588 :     if (now < std::max(s->deadline, s->hold)) {
      47          616 :         arm(s);
      48          616 :         return;
      49              :     }
      50         4972 :     s->armed = false;
      51              :     // `s` keeps the callback alive if it destroys the watchdog; nothing touches it afterwards
      52         4972 :     s->on_expired();
      53         5598 : }
      54              : 
      55              : }
        

Generated by: LCOV version 2.0-1