Fix task may appear to be triggered more than 1 second late #27
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The calculation of next trigger time do not discard fractional seconds. Depending on the exact timing of ticking, the task may appear to be triggered more than 1 second late, despite properly ticked every second.
Example: Suppose a task is scheduled to trigger at 00 second, but the calculated next trigger time is at 00.5 second, while
tick()
is happening at every .35 second. At 00.35 second a tick happened, but because 00.35 < 00.5 the task is not triggered. It will be triggered in the next tick that's at 01.35 second, which appeared to be late for 1.35 second (despiteget_delay()
will return 1.35 - 0.5 = 0.85 second in this case).The source of the fractional seconds is from the
from
argument, wherenow()
, a clock that usually have sub-second precision, is passed. If during the calculation,date_changed
is nevertrue
, the variablecurr
will only be modified through+=
and-=
in the second half of the function, where the increments and/or decrements are all multiple of whole seconds.This fix calculates the fractional second by modulo 1 second, then subtracted that from the calculated time. Since the trigger time is now scheduled at exact second, whenever tick happened within that second the task will be triggered. Doing floor by
std::duration_cast<>
is not good because it changes theduration
type (because of differentratio
), and therefore the thetime_point
type (because of differentduration
).