Skip to content

Commit efeb1e4

Browse files
committed
Fixed problem where multiple ticks within the same second causes task to expire multiple times that second.
1 parent 392948c commit efeb1e4

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

libcron/Cron.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ namespace libcron
6868
}
6969
};
7070

71+
7172
Queue tasks{};
7273
ClockType clock{};
7374
bool first_tick = true;
@@ -112,6 +113,21 @@ namespace libcron
112113
{
113114
size_t res = 0;
114115

116+
if(!first_tick)
117+
{
118+
// Only allow time to flow if at least one second has passed since the last tick,
119+
// either forward or backward.
120+
auto diff = now - last_tick;
121+
122+
constexpr auto one_second = std::chrono::seconds{1};
123+
124+
if(diff < one_second && diff > -one_second)
125+
{
126+
now = last_tick;
127+
}
128+
}
129+
130+
115131
if (first_tick)
116132
{
117133
first_tick = false;

test/CronTest.cpp

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,11 @@ SCENARIO("Clock changes")
240240

241241
WHEN("Clock changes <3h forward")
242242
{
243-
THEN("Task expires accordingly")
244-
{
245-
REQUIRE(c.tick() == 1);
246-
clock.add(minutes{ 30 }); // 00:30
247-
REQUIRE(c.tick() == 0);
243+
THEN("Task expires accordingly")
244+
{
245+
REQUIRE(c.tick() == 1);
246+
clock.add(minutes{30}); // 00:30
247+
REQUIRE(c.tick() == 0);
248248
clock.add(minutes{30}); // 01:00
249249
REQUIRE(c.tick() == 1);
250250
REQUIRE(c.tick() == 0);
@@ -296,4 +296,42 @@ SCENARIO("Clock changes")
296296
}
297297
}
298298
}
299+
}
300+
301+
SCENARIO("Multiple ticks per second")
302+
{
303+
Cron<TestClock> c{};
304+
auto& clock = c.get_clock();
305+
306+
auto now = sys_days{2018_y / 05 / 05};
307+
clock.set(now);
308+
309+
int run_count = 0;
310+
311+
// Every 10 seconds
312+
REQUIRE(c.add_schedule("Clock change task", "*/10 0 * * * ?", [&run_count]()
313+
{
314+
run_count++;
315+
})
316+
);
317+
318+
c.tick(now);
319+
320+
REQUIRE(run_count == 1);
321+
322+
WHEN("Many ticks during one seconds")
323+
{
324+
for(auto i = 0; i < 10; ++i)
325+
{
326+
clock.add(std::chrono::microseconds{1});
327+
c.tick();
328+
}
329+
330+
THEN("Run count has not increased")
331+
{
332+
REQUIRE(run_count == 1);
333+
}
334+
335+
}
336+
299337
}

0 commit comments

Comments
 (0)