The REMOVE-TIMER issue:
People here might remember a previous post of mine suspecting a problem
with timers of the multiplexer. Well lately with more testing, I've
noticed the issue again, and that this only occurs on restartable
timers which I want to conditionally disable.
After looking at the source, I discovered the obvious reason: my test
case used REMOVE-TIMER as part of its timeout handler code, while the
time scheduler reschedules/restarts non-:one-shot timers after the
handler callback returns. It would be possible to modify the scheduler
so that REMOVE-TIMER be callback-safe, but it probably isn't a
requirement, considering that for such cases :one-shot can easily be
used and as wanted the user code could restart the timer anyway if
wanted later on.
Thus it is probably best to simply document this in the API, I simply
made wrong assumptions about the timer scheduler mechanism.
Redundant multiplexer code:
This currently only is at the stage of a pipe-dream (not yet a project)
but I've sometimes been thinking about rewriting the multiplexer so the
main code be more tailored to kqueue, so that redundant sanity checking
code and timer scheduler wouldn't have to be used with that backend, and
other backends could share a library based on the current code for the
scheduler and all the sanity checking.
To explain better about the redundancy overhead:
- Kqueue drops any registered events for an fd at fd close time.
Thus only timers would have to be unregistered (which can be made via
a single syscall, or can pend in an array to pass to the next natural
single syscall of the main scheduler loop).
- Kqueue also allows to use a per-event user-data pointer which can be
used to efficiently map to internal user objects, eliminating the
need for custom fd->object (or timerid->object) indexing tables.
This udata is returned by the framework at both event reception and
errors (which are simply provided as events).
- Event registration, cancellation and polling are all done in a single
call to kevent, and kevent can report if an filter was already
registered or not, precisely, removing the need for userland code
to maintain redundant tables and related sanity checks.
- kqueue also supports timers (one-shot and restarting ones).
Restartable timers are atomically restarted so userland doesn't have
to care. A timeout callback could use REMOVE-TIMER which would
simply add an element to the kevent array which'd be passed to the
next syscall in the main loop.
Of course if REMOVE-TIMER was declared callback-safe, the userland
scheduler for less powerful backends would probably also be fixed
to flag timers in a way for them not to be rescheduled.
Moving timers to backends which support it would be more efficient
than the user rolled timer scheduler code.
But then again, I'll use the current iolib multiplexer for now, as long
as it works :)
--
Matt