summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2022-06-17 17:05:10 +0200
committerAlbrecht Schlosser <albrechts.fltk@online.de>2022-06-17 17:05:10 +0200
commitf3bf231cc06ab82576b798a1f615981924a2903c (patch)
treeb9d00b2b6c8a1ea1fc3c5385401f0e25f579cccf /src
parentd8eb1f9ca465ca685a67203df38616a13bd82bb4 (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.
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Timeout.cxx28
-rw-r--r--src/Fl_Timeout.h2
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() {}