[fltk/fltk] Using Fl_Callback_Interface with Fl_Timeout (Fl::add_timeout(), Fl::repeat_timeout()) (PR #1600)
Matthias Melcher
06:35 Sep 04
This PR is less for merging and more to show how Fl_Callback_Interface would work with Fl_Timeout.
I am pretty sure this will be rejected - at least in this extreme - because it does add the "templatefication" that we do not want. It's a readability issue though. On the functional side, this is quite awesome.
So what are we doing here. Fl::add_timeout() calls static Fl_Timeout::add_timeout() which manages a list of pending and unused Fl_Timeout instances. The only supported callback is void()(void*). Making Fl_Callback_Interface a base class of Fl_Timeout adds all the other callback convenience that is now in Fl_Widget, plus being back compatible for creating timeouts.
Well, what are the drawbacks?
1
First of all, we have an API for removing timeouts that does not work with lambdas. Fl::remove_timeout(callback, user_data) can't work, because std::function does not ever return a unique address of anything.
Well, this is solvable if Fl::add_timeout() returns a pointer to Fl_Timeout, right? No, because when a timer expires, Fl_Timeout becomes invalid after the callback. Calling Fl::remove_timeout(Fl_Timout* t) after a certain time would be undefined.
The solution would be to return an ever increasing Fl_Timeout_ID, and add Fl::remove_timeout(Fl_Timeout_ID) which would only remove a timer if it was still pending. SO that is solvable, but adds a new (and improved) API.
2
The second feature is completely optional, and the issue with it is scary and amazing at the same time. In the code for Fl_Timeout, I implemented static Fl_Timeout::add_timeout() with a template:
What this odes is amazing: for every FL_Callback_Interface::callback(...) function, the compiler creates a corresponding Fl_Timeout::add_timeout(double, ...) function, if required. So with just four lines of code, we get 11 new Fl::add_timeout() functions. Wow!
Since all the template features of C++ are only available in header files, Fl_Timeout would need to be public in the FL header directory.
new APIs
To illustrate, if implemented all the way, we get the following APIs and even more, and they only generate code if they are actually used:
// lambdas:
Fl::add_timeout( 3.0, [something]() { something->run(); } )
// and we can serve these callbacks:
void ()(void*);
void ()(long);
void ()(Fl_Timeout*);
void ()(Fl_Timeout*, void*);
// etc.
Example
// A set-and-forget timer, classic style, with allocated data
void timer_cb(void *u) {
// do something with 'u'
}
void free_cb(void* u) {
::free(u);
}
void* important_data = malloc(3, 1024);
Fl::add_timeout(5.0, timer_cb, important_data, free_cb);
// important_data will be free'd by FLTK after the timer callback returns
You can view, comment on, or merge this pull request online at:
— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: <fltk/fltk/pull/1600@github.com>
Comments are owned by the poster. All other content is copyright 1998-2026 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.