[][src]Module libpulse_binding::mainloop

Main loop abstraction layer.

Main Loop Abstraction

Both the PulseAudio core and the PulseAudio client library use a main loop abstraction layer. Due to this it is possible to embed PulseAudio into other applications easily.

This abstraction contains three basic elements:

  • Deferred events: Events that will trigger as soon as possible. Note that some implementations may block all other events when a deferred event is active.
  • I/O events: Events that trigger on file descriptor activities.
  • Timer events: Events that trigger after a fixed amount of time.

The abstraction is represented as a number of function pointers in the mainloop::api::MainloopApi structure.

To actually be able to use these functions, an implementation needs to be coupled to the abstraction. There are three of these shipped with PulseAudio, but any other can be used with a minimal amount of work, provided it supports the three basic events listed above.

The implementations shipped with PulseAudio are:

  • Standard: A minimal but fast implementation based on the C library’s poll() function.
  • Threaded: A special version of the previous implementation where all of PulseAudio’s internal handling runs in a separate thread.
  • ‘Glib’: A wrapper around GLib’s main loop. This is provided in the separate libpulse_glib_binding crate.

UNIX signals may be hooked to a main loop using the functionality from mainloop::signal. This relies only on the main loop abstraction and can therefore be used with any of the implementations.

Callback Notes

Execution

As described in the standard mainloop documentation, there are three phases to mainloop execution, and the third - ‘dispatch’ - is when user callbacks get executed.

It is important to understand that while it is typical that user callbacks are executed by the mainloop’s dispatcher, callback execution is not exclusively done there; in some cases callbacks get executed directly in synchronous function execution. For instance, if you set up a context state change callback, then try to connect the context object, execution of the ‘connect’ function call involves (internally within the PulseAudio client library) direct execution of this callback in setting the initial connection state. After returning, the callback is then on only executed asynchronously from the mainloop’s dispatcher.

While execution using the Standard mainloop is entirely synchronous, the Threaded mainloop implementation runs the standard mainloop in a separate thread and callback execution occurs asynchronously, requiring careful use of the mainloop’s lock method. When writing callbacks with the Threaded mainloop, users must beware the potential that in a few cases the callback may be executed in two different scenarios, and with different threads. Note that the threaded mainloop has an in_thread method for determining whether or not the thread it it is executed from is the special event loop thread.

Queued Events and Changing Callbacks

It is also worth understanding that any events that get queued for dispatch do not hold cached copies of user callback parameters. Where applicable, you can thus freely and safely change the set callback, with that change taking effect immediately to all future event dispatching.

Threading and Rc

Normally when holding multiple references to objects across threads in Rust you would use an Arc wrapper. However, with the Threaded mainloop, you may be able to get away with using just an Rc wrapper. Remember that with the Threaded mainloop you must use it’s lock method to synchronise access to objects, and so you know that at any one moment either your thread (when you take the lock) or the event loop thread hold the lock, never both, and thus only one thread is ever working with objects at any one time, and since Rust actually has no idea that more than one thread is involved (hidden in the C library’s implementation), you can safely get away with using Rc.

Modules

api

Main loop abstraction layer API.

events

Main loop events.

signal

UNIX signal support for main loops.

standard

Standard/minimal main loop implementation based on poll().

threaded

A variation of the standard main loop implementation, using a background thread.