Add Fl::remove_next_timeout(...) to remove only one timeout (#992)

This method also returns the data pointer of the removed timeout.

This new method is generally useful for user code and particularly
necessary to fix issue #991.

Co-authored-by: Albrecht Schlosser <albrechts.fltk@online.de>
This commit is contained in:
Albrecht Schlosser 2024-06-21 17:35:01 +02:00 committed by GitHub
parent 5ee1c0c9df
commit 456d53c403
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 110 additions and 10 deletions

View File

@ -479,6 +479,7 @@ public:
static void repeat_timeout(double t, Fl_Timeout_Handler cb, void *data = 0);
static int has_timeout(Fl_Timeout_Handler cb, void *data = 0);
static void remove_timeout(Fl_Timeout_Handler cb, void *data = 0);
static int remove_next_timeout(Fl_Timeout_Handler cb, void *data = 0, void **data_return = 0);
static void add_check(Fl_Timeout_Handler, void* = 0);
static int has_check(Fl_Timeout_Handler, void* = 0);

View File

@ -1,7 +1,7 @@
//
// Main event handling code for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2023 by Bill Spitzak and others.
// Copyright 1998-2024 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -344,24 +344,69 @@ int Fl::has_timeout(Fl_Timeout_Handler cb, void *data) {
}
/**
Removes a timeout callback from the timer queue.
Remove one or more matching timeout callbacks from the timer queue.
This method removes all matching timeouts, not just the first one.
This may change in the future.
This method removes \b all matching timeouts, not just the first one.
If the \p data argument is \p NULL (the default!) only the callback
\p cb must match, i.e. all timer entries with this callback are removed.
It is harmless to remove a timeout callback that no longer exists.
If you want to remove only the next matching timeout you can use
Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return)
(available since FLTK 1.4.0).
\param[in] cb Timer callback to be removed (must match)
\param[in] data Wildcard if NULL (default), must match otherwise
\see Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return)
*/
void Fl::remove_timeout(Fl_Timeout_Handler cb, void *data) {
Fl_Timeout::remove_timeout(cb, data);
}
/**
Remove the next matching timeout callback and return its \p data pointer.
This method removes only the next matching timeout and returns in
\p data_return (if non-NULL) the \p data member given when the timeout
was scheduled.
This method is useful if you remove a timeout before it is scheduled
and you need to get and use its data value, for instance to free() or
delete the data associated with the timeout.
This method returns non-zero if a matching timeout was found and zero
if no timeout matched the request.
If the return value is \c N \> 1 then there are N - 1 more matching
timeouts pending.
If you need to remove all timeouts with a particular callback \p cb
you must repeat this call until it returns 1 (all timeouts removed)
or zero (no matching timeout), whichever occurs first.
\param[in] cb Timer callback to be removed (must match)
\param[in] data Wildcard if NULL, must match otherwise
\param[inout] data_return Pointer to (void *) to receive the data value
\return non-zero if a timer was found and removed
\retval 0 no matching timer was found
\retval 1 the last matching timeout was found and removed
\retval N>1 a matching timeout was removed and there are \n
(N - 1) matching timeouts pending
\see Fl::remove_timeout(Fl_Timeout_Handler cb, void *data)
\since 1.4.0
*/
int Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) {
return Fl_Timeout::remove_next_timeout(cb, data, data_return);
}
////////////////////////////////////////////////////////////////
// Checks are just stored in a list. They are called in the reverse

View File

@ -210,7 +210,9 @@ void Fl_Timeout::insert() {
\retval 0 not found
\retval 1 found
Implements Fl::has_timeout(Fl_Timeout_Handler cb, void *data)
Implements:
int Fl::has_timeout(Fl_Timeout_Handler cb, void *data)
\see Fl::has_timeout(Fl_Timeout_Handler cb, void *data)
*/
@ -232,7 +234,9 @@ int Fl_Timeout::has_timeout(Fl_Timeout_Handler cb, void *data) {
\param[in] cb callback function
\param[in] data optional user data (default: \p NULL)
Implements Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *data)
Implements:
void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *data)
\see Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *data)
*/
@ -250,7 +254,9 @@ void Fl_Timeout::add_timeout(double time, Fl_Timeout_Handler cb, void *data) {
\param[in] cb callback function
\param[in] data optional user data (default: \p NULL)
Implements Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data)
Implements:
void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data)
\see Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data)
*/
@ -276,7 +282,9 @@ void Fl_Timeout::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data)
\param[in] cb Timer callback to be removed (must match)
\param[in] data Wildcard if NULL, must match otherwise
Implements Fl::remove_timeout(Fl_Timeout_Handler cb, void *data)
Implements:
void Fl::remove_timeout(Fl_Timeout_Handler cb, void *data)
\see Fl::remove_timeout(Fl_Timeout_Handler cb, void *data)
*/
@ -293,6 +301,49 @@ void Fl_Timeout::remove_timeout(Fl_Timeout_Handler cb, void *data) {
}
}
/**
Remove the next matching timeout callback and return its \p data pointer.
Implements:
int Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return)
\param[in] cb Timer callback to be removed (must match)
\param[in] data Wildcard if NULL, must match otherwise
\param[inout] data_return pointer to void * to receive the data value
\return non-zero if a timer was found and removed
\retval 0 no matching timer was found
\retval 1 the last matching timeout was found and removed
\retval N>1 a matching timeout was removed and there are\n
(N - 1) matching timeouts pending
For details
\see Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return)
*/
int Fl_Timeout::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) {
int ret = 0;
for (Fl_Timeout** p = &first_timeout; *p;) { // scan all timeouts
Fl_Timeout* t = *p;
if (t->callback == cb && (t->data == data || !data)) { // timeout matches
ret++;
if (ret == 1) { // first timeout: remove
if (data_return)
*data_return = t->data;
*p = t->next;
t->next = free_timeout;
free_timeout = t;
continue;
}
p = &(t->next);
} // timeout matches
else { // no match
p = &(t->next);
}
} // scan all timeouts
return ret;
}
/**
Remove the timeout from the active timer queue and push it onto
the stack of currently running callbacks.

View File

@ -2,7 +2,7 @@
// Header for timeout support functions for the Fast Light Tool Kit (FLTK).
//
// Author: Albrecht Schlosser
// Copyright 2021-2022 by Bill Spitzak and others.
// Copyright 2021-2024 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -31,6 +31,7 @@
- Fl::repeat_timeout()
- Fl::has_timeout()
- Fl::remove_timeout()
- Fl::remove_next_timeout()
and related methods of class Fl_Timeout.
*/
@ -49,6 +50,7 @@
- Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data)
- Fl::has_timeout(Fl_Timeout_Handler cb, void *data)
- Fl::remove_timeout(Fl_Timeout_Handler cb, void *data)
- Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return)
*/
class Fl_Timeout {
@ -106,6 +108,7 @@ public:
static void add_timeout(double time, Fl_Timeout_Handler cb, void *data);
static void repeat_timeout(double time, Fl_Timeout_Handler cb, void *data);
static void remove_timeout(Fl_Timeout_Handler cb, void *data);
static int remove_next_timeout(Fl_Timeout_Handler cb, void *data = NULL, void **data_return = NULL);
// Elapse timeouts, i.e. calculate new delay time of all timers.
// This does not call the timer callbacks.