Reputation: 51
Currently, im working on an embedded project, where most of the subsystems are based on timing.
i have searched for many solutions to avoid issues with timers rolling over, but one thing still puzzles me.
At present time, i am using the twos complement of unsigned long's like this.
ulong t1 = tick of last event;
ulong t2 = current tick;
if ( t2 - t1 >= limit ){
do something
}
Others have suggested, that it is necessary to cast the result of t2-t1 to a signed entity, before this will work, but that i can't understand why. Any other insights or suggestions?
Upvotes: 5
Views: 1860
Reputation: 1362
Sometimes I do it like this:
ulong t1 = tick of last event;
ulong t2 = current tick;
if ( t1 > t2 ){
if ((ULONG_MAX-t1+t2+1)>=limit){
do something
}
} else {
if ( t2 - t1 >= limit ){
do something
}
Upvotes: 2
Reputation: 3825
You don't have to cast it to signed. If "do something" is alarm handling code and limit is time interval.
The best practice of the regular intervals is:
ulong next_alarm_ticks = 0;
void poll_alarm()
{
if (get_ticks() - next_alarm_ticks < ULONG_MAX/2) {
// current time is "greater" than next_alarm_ticks
handle_alarm();
next_alarm_ticks += alarm_interval;
}
}
Upvotes: 0
Reputation: 183978
If it is guaranteed that t2
is conceptually always larger than t1
, casting to a signed entity would be wrong. Arithmetic of unsigned integers is guaranteed by the standard to be correct modulo UTYPE_MAX + 1
, so the difference t2 - t1
will be correct modulo ULONG_MAX + 1
when calculated as unsigned long
s. When casting to a signed entity, the behaviour is implementation defined if the value is not representable in the target type. Often that converts large positive values to negative values.
The test
if ( t2 - t1 >= limit ){
will break down if the difference between the current tick count and the previous without wrapping of the timer becomes larger than ULONG_MAX
, but otherwise it works.
But if t2
could be earlier than t1
, the true difference t2 - t1
would be negative, but as an unsigned long
, it would be a potentially large positive number. Then casting to a signed type can work correctly in cases where using unsigned types doesn't.
Upvotes: 0