Event Loops and Event Sources

Ase event loops are a programming facility to execute callback handlers (dispatch event sources) according to expiring Timers, IO events or arbitrary other conditions. A Ase::EventLoop is created with Ase::MainLoop::_new() or Ase::MainLoop::create_sub_loop(). Callbacks or other event sources are added to it via Ase::EventLoop::add(), Ase::EventLoop::exec_normal() and related functions. Once a main loop is created and its callbacks are added, it can be run as:

while (!loop.finishable())
  loop.iterate (true);

Ase::MainLoop::iterate() finds a source that immediately need dispatching and starts to dispatch it. If no source was found, it monitors the source list's PollFD descriptors for events, and finds dispatchable sources based on newly incoming events on the descriptors. If multiple sources need dispatching, they are handled according to their priorities (see Ase::EventLoop::add()) and at the same priority, sources are dispatched in round-robin fashion. Calling Ase::MainLoop::iterate() also iterates over its sub loops, which allows to handle sources on several independently running loops within the same thread, usually used to associate one event loop with one window.

Traits of the Ase::EventLoop class:

  • The main loop and its sub loops are handled in round-robin fahsion, priorities below Ase::EventLoop::PRIORITY_ASCENT only apply internally to a loop.
  • Loops are thread safe, so any thready may add or remove sources to a loop at any time, regardless of which thread is currently running the loop.
  • Sources added to a loop may be flagged as "primary" (see Ase::EventSource::primary()), to keep the loop from exiting. This is used to distinguish background jobs, e.g. updating a window's progress bar, from primary jobs, like processing events on the main window. Sticking with the example, a window's event loop should be exited if the window vanishes, but not when it's progress bar stoped updating.

Loop integration of a Ase::EventSource class:

  • First, prepare() is called on a source, returning true here flags the source to be ready for immediate dispatching.
  • Second, poll(2) monitors all PollFD file descriptors of the source (see Ase::EventSource::add_poll()).
  • Third, check() is called for the source to check whether dispatching is needed depending on PollFD states.
  • Fourth, the source is dispatched if it returened true from either prepare() or check(). If multiple sources are ready to be dispatched, the entire process may be repeated several times (after dispatching other sources), starting with a new call to prepare() before a particular source is finally dispatched.