Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify data type for time variables #3

Merged
merged 1 commit into from
Mar 6, 2017
Merged

Unify data type for time variables #3

merged 1 commit into from
Mar 6, 2017

Conversation

PhirePhly
Copy link
Contributor

The three variables used in the main loop were all different data types, which would likely cause roll-over issues at ~25 or ~50 days of run time.

This fix changes the api_mtbs and api_lasttime to match the unsigned long type used by the millis() function and tweaks the main loop comparison.

I will admit I haven't produced the original possible issue or tested the fix, since it would take several months to do so. At the very least, the time variables are now the same datatype.

The three variables used in the main loop were all different data types,
which would likely cause roll-over issues at ~25 or ~50 days of run time.

This fix changes the api_mtbs and api_lasttime to match the unsigned long
type used by the millis() function and tweaks the main loop comparison.
@witnessmenow
Copy link
Owner

witnessmenow commented Mar 4, 2017

Hey @PhirePhly , very valid issue especially for something that is intended to be long running like this.

Your fix can also run into issues though, eventually millis() will start returning 0 again and once that happens your if loop will not return true again:

now - lastRunTime > timeBetweenRuns
// After Overflow of millis would be
0 - Bignumber > 2000 (this can't be true)

maybe this would work

unsigned long difference = now - lastRunTime;
if ( (difference > timeBetweenRuns) || (difference < 0 ))

that should handle the overflow case. The difference should never be less than 0 unless the overflow has happened

EDIT: just to mention that my current code also suffers from this! Just re-reading it makes it sound like I'm blaming you for it, not my intention at all! :)

@PhirePhly
Copy link
Contributor Author

No worries. I'm used to terse PR feedback.

The issue with your counter-example is that difference is unsigned, so it will (by definition) never be less than 0. (difference < 0) will never be true.

I think my patch does still handle the over-flow case correctly:

  1. Update happens and lastRunTime is set to something near ULONG_MAX
  2. millis() rolls over and starts back at zero
  3. The next calculation of millis() - lastRunTime is now a small number minus something near ULONG_MAX. This underflows the calculation and takes us all the way around to something slightly larger than the value of millis(), which is the result that is desired here

The issue is that you want everything to have the same data type so there's no weird promotions happening between data types while you're relying on this overflow/underflow behavior to handle rollover.

Example:

unsigned long lastRunTime = 4294967196;
unsigned long now = 100;
now - lastRunTime == 200;

(I believe ULONG_MAX is 4294967295 in this environment)

@witnessmenow witnessmenow merged commit ee9eb09 into witnessmenow:master Mar 6, 2017
@witnessmenow
Copy link
Owner

Thanks for the explanation! Merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants