diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2022-06-17 17:05:10 +0200 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2022-06-17 17:05:10 +0200 |
| commit | f3bf231cc06ab82576b798a1f615981924a2903c (patch) | |
| tree | b9d00b2b6c8a1ea1fc3c5385401f0e25f579cccf | |
| parent | d8eb1f9ca465ca685a67203df38616a13bd82bb4 (diff) | |
Improve reliability of timeout handling (#450, part 1)
This commit prevents "timer loops" without intermediate event handling
if callback handling takes longer than the timer delay of repeating
timers.
For more details see GitHub issue #450.
| -rw-r--r-- | src/Fl_Timeout.cxx | 28 | ||||
| -rw-r--r-- | src/Fl_Timeout.h | 2 |
2 files changed, 24 insertions, 6 deletions
diff --git a/src/Fl_Timeout.cxx b/src/Fl_Timeout.cxx index 21200462d..f93b86354 100644 --- a/src/Fl_Timeout.cxx +++ b/src/Fl_Timeout.cxx @@ -162,9 +162,9 @@ void Fl_Timeout::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data) Fl_Timeout *cur = current_timeout; if (cur) { t->time += cur->time; // was: missed_timeout_by (always <= 0.0) + if (t->time < 0.0) + t->time = 0.001; // at least 1 ms } - if (t->time < 0.0) - t->time = 0.001; // at least 1 ms t->insert(); } @@ -245,8 +245,8 @@ void Fl_Timeout::release() { current_timeout = t->next; } // put the timer into the list of free timers - t->next = free_timeout; - free_timeout = t; + next = free_timeout; + free_timeout = this; } /** @@ -317,6 +317,7 @@ Fl_Timeout *Fl_Timeout::get(double time, Fl_Timeout_Handler cb, void *data) { } t->next = 0; + t->skip = 1; // see do_timeouts() (issue #450) t->delay(time); t->callback = cb; t->data = data; @@ -358,11 +359,26 @@ void Fl_Timeout::elapse_timeouts() { Elapse timers and call their callbacks if any timers are expired. */ void Fl_Timeout::do_timeouts() { + + // Reset "skip" flag for existing timers (issue #450). + // For timers inserted in timer callbacks 'skip' will be true (1) + + Fl_Timeout *t = first_timeout; + while (t) { + t->skip = 0; + t = t->next; + } + if (first_timeout) { Fl_Timeout::elapse_timeouts(); - Fl_Timeout *t; - while ((t = Fl_Timeout::first_timeout)) { + while ((t = first_timeout)) { if (t->time > 0) break; + + // skip timers inserted during timeout handling (issue #450) + while (t && t->skip) + t = t->next; + if (!t || t->time > 0) break; + // make this timeout the "current" timeout t->make_current(); // now it is safe for the callback to do add_timeout: diff --git a/src/Fl_Timeout.h b/src/Fl_Timeout.h index 610f00067..8cff84689 100644 --- a/src/Fl_Timeout.h +++ b/src/Fl_Timeout.h @@ -51,6 +51,7 @@ protected: Fl_Timeout_Handler callback; // the user's callback void *data; // the user's callback data double time; // delay until timeout + int skip; // skip "new" (inserted) timers (issue #450) // constructor Fl_Timeout() { @@ -58,6 +59,7 @@ protected: callback = 0; data = 0; time = 0; + skip = 0; } ~Fl_Timeout() {} |
