diff --git a/libcron/Cron.h b/libcron/Cron.h index 4b0802d..b4101a0 100644 --- a/libcron/Cron.h +++ b/libcron/Cron.h @@ -68,6 +68,7 @@ namespace libcron } }; + Queue tasks{}; ClockType clock{}; bool first_tick = true; @@ -112,6 +113,21 @@ namespace libcron { size_t res = 0; + if(!first_tick) + { + // Only allow time to flow if at least one second has passed since the last tick, + // either forward or backward. + auto diff = now - last_tick; + + constexpr auto one_second = std::chrono::seconds{1}; + + if(diff < one_second && diff > -one_second) + { + now = last_tick; + } + } + + if (first_tick) { first_tick = false; diff --git a/test/CronTest.cpp b/test/CronTest.cpp index ec54f51..b1ee940 100644 --- a/test/CronTest.cpp +++ b/test/CronTest.cpp @@ -240,11 +240,11 @@ SCENARIO("Clock changes") WHEN("Clock changes <3h forward") { - THEN("Task expires accordingly") - { - REQUIRE(c.tick() == 1); - clock.add(minutes{ 30 }); // 00:30 - REQUIRE(c.tick() == 0); + THEN("Task expires accordingly") + { + REQUIRE(c.tick() == 1); + clock.add(minutes{30}); // 00:30 + REQUIRE(c.tick() == 0); clock.add(minutes{30}); // 01:00 REQUIRE(c.tick() == 1); REQUIRE(c.tick() == 0); @@ -296,4 +296,42 @@ SCENARIO("Clock changes") } } } +} + +SCENARIO("Multiple ticks per second") +{ + Cron c{}; + auto& clock = c.get_clock(); + + auto now = sys_days{2018_y / 05 / 05}; + clock.set(now); + + int run_count = 0; + + // Every 10 seconds + REQUIRE(c.add_schedule("Clock change task", "*/10 0 * * * ?", [&run_count]() + { + run_count++; + }) + ); + + c.tick(now); + + REQUIRE(run_count == 1); + + WHEN("Many ticks during one seconds") + { + for(auto i = 0; i < 10; ++i) + { + clock.add(std::chrono::microseconds{1}); + c.tick(); + } + + THEN("Run count has not increased") + { + REQUIRE(run_count == 1); + } + + } + } \ No newline at end of file