diff --git a/timerfd_manager.cpp b/timerfd_manager.cpp index e89b2069..c7bc736b 100644 --- a/timerfd_manager.cpp +++ b/timerfd_manager.cpp @@ -80,6 +80,7 @@ void timerfd_manager_t::clear_timer(int timer_id) void timerfd_manager_t::set_nearest() { +again: if (!timers.size()) { nearest = -1; @@ -115,6 +116,12 @@ void timerfd_manager_t::set_nearest() exp.it_value.tv_sec--; exp.it_value.tv_nsec += 1000000000; } + if (exp.it_value.tv_sec < 0 || !exp.it_value.tv_sec && !exp.it_value.tv_nsec) + { + // It already happened + trigger_nearest(); + goto again; + } if (timerfd_settime(timerfd, 0, &exp, NULL)) { throw std::runtime_error(std::string("timerfd_settime: ") + strerror(errno)); @@ -129,19 +136,24 @@ void timerfd_manager_t::handle_readable() size_t res = read(timerfd, &n, 8); if (res == 8 && nearest >= 0) { - int nearest_id = timers[nearest].id; - auto cb = timers[nearest].callback; - if (timers[nearest].repeat) - { - inc_timer(timers[nearest]); - } - else - { - timers.erase(timers.begin()+nearest, timers.begin()+nearest+1); - } - cb(nearest_id); - nearest = -1; + trigger_nearest(); } wait_state = 0; set_nearest(); } + +void timerfd_manager_t::trigger_nearest() +{ + int nearest_id = timers[nearest].id; + auto cb = timers[nearest].callback; + if (timers[nearest].repeat) + { + inc_timer(timers[nearest]); + } + else + { + timers.erase(timers.begin()+nearest, timers.begin()+nearest+1); + } + cb(nearest_id); + nearest = -1; +} diff --git a/timerfd_manager.h b/timerfd_manager.h index 14e70840..8f438e38 100644 --- a/timerfd_manager.h +++ b/timerfd_manager.h @@ -23,6 +23,8 @@ class timerfd_manager_t void inc_timer(timerfd_timer_t & t); void set_nearest(); + void trigger_nearest(); + void handle_readable(); public: std::function)> set_fd_handler; @@ -30,5 +32,4 @@ public: ~timerfd_manager_t(); int set_timer(uint64_t millis, bool repeat, std::function callback); void clear_timer(int timer_id); - void handle_readable(); };