Le lundi 5 juillet 2021 à 22:02:45 UTC+2, Albrecht Schlosser a écrit :
@Manolo: Before you dive too deep into a specific implementation for
Wayland I'd like to share some thoughts I'm having since some time
now to unify the timer handling on all platforms. I believe that the
Linux timer implementation is superior to the Windows and maybe also
the macOS implementation. The Linux timer implementation works like
this (maybe over-simplified):
I believe this means the timer implementation for the X11 FLTK platform (which covers Linux but also Unix and Darwin).
(1) Every call to Fl::add_timeout() or Fl::repeat_timeout() adds a
timer entry to the internal timer queue. This queue is sorted by the
timer's due time.
(2) There's only one system timer, using the smallest delta value,
i.e. the time of the first timer in the queue.
In my view, there's no system timer at all. FLTK sets the max length of the next select/poll call to the smallest delta value,
which has the effect of breaking the event loop at the desired time. This setup is possible because with X11 (and with Wayland too)
the event loop is built using a select/poll call that returns when data arrive on a fd or when the waiting delay expires.
(3) Whenever the timer triggers (or maybe more often) the event
handling decrements the delta time of all timers.
I find this procedure awkward, even though it's correct.
(4) All timers callbacks of expired timers are called.
(5) A new timer with the shortest delay (which is always the first
timer in the queue) is scheduled.
(6) Wait for timer events...
In my view, there're no real timer events: the poll/select call expires.
This is AFAICT done because the standard Unix timers can be
interrupted and need to re-scheduled whenever such interrupts occur.
The benefit of this approach is as described in Fl::repeat_timer()
docs: if the call to Fl::repeat_timer() is done "late" it can be
corrected by the delay and the overall timer sequence of repeated
timers is more accurate than on other platforms.
On the Windows platform we're (AFAICT) using one system timer per
Fl::add/repeat_timer() call. The Windows timer events are less
accurate anyway, but a change as designed for Unix/Linux could
probably contribute to more accuracy of repeated timer events
because the correction of timer delay as on Unix/Linux could work
better (it does not currently on Windows).
I know less about the macOS platform, but I know for sure that the
timer handling is different. There are inconsistencies WRT
Unix/Linux/Windows on the user visible level (which I intend to
demonstrate with a test program anyway) but which are too difficult
(and OT now).
The macOS FLTK platform uses a system timer: the event loop is made by calling a function that does "wait until an event arrives",
and Fl::add_timeout creates a system object that makes the waiting function run the timer cb when the delay has expired.
My idea was to also use a true system timer for the Wayland platform (but that could be for all Linux). Posix timers do that.
They trigger either a signal or a thread after a specified delay. With the thread approach, having the child thread call Fl::awake(cb, data)
allows the main thread to stop waiting and process the timeout cb.
That all said: I hope that the Wayland implementation would be
basically like the Unix/Linux timer queue handling so we can easily
unify all platforms.
More about the unification: I'm thinking of a platform independent
timer queue where Fl::add_timeout() and friends would be platform
independent. They would add an Fl_Timeout_XX object to the timer
queue which may contain platform specific timer data (or
not?). Triggering the timeout would then, as always, be done by the
system, the timer queue handling would still be platform
independent, as well as calling the callbacks etc.. The more I think
about it, the more I believe that only the scheduling of this single
timer event would be a platform dependent (i.e. system driver)
function.
As written above, the X11 approach uses the fd through which all X11 data arrives and the poll/select call on this fd to simulate
timeout events: it reduces the max waiting time of the poll/select call. Is your idea to change the organization of the event loop
of other platforms (namely macOS) and have it wait for GUI events for a time determined by the next scheduled timeout?
Comments welcome, particularly from Manolo but also from other devs.
If I'm not missing anything (are there any drawbacks?) I could start
soon to develop a new timeout handling model which does all of this
as described.