diff options
author | Arun Raghavan <arun@accosted.net> | 2014-09-29 22:48:16 +0530 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2014-10-14 09:28:56 +0200 |
commit | 760968e8e5711ffe66c825be517cd34bd040ef47 (patch) | |
tree | c5ccb41263975274aff97b877bb1e929d9645403 | |
parent | 6279f682e8749c793f95d93fb37e9e7bbcb09cb2 (diff) |
pulse: Add some documentation about threading and synchronisation
This gives a quick introduction to how the pulsesink/pulsesrc code
interacts with the pa_threaded_mainloop that we start up to communicate
with the server.
-rw-r--r-- | ext/pulse/pulsesink.c | 28 | ||||
-rw-r--r-- | ext/pulse/pulsesrc.c | 3 |
2 files changed, 29 insertions, 2 deletions
diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c index e77ce8d5e..e3cdf05b4 100644 --- a/ext/pulse/pulsesink.c +++ b/ext/pulse/pulsesink.c @@ -107,6 +107,30 @@ typedef struct _GstPulseRingBufferClass GstPulseRingBufferClass; typedef struct _GstPulseContext GstPulseContext; +/* A note on threading. + * + * We use a pa_threaded_mainloop to interact with the PulseAudio server. This + * starts up a separate thread that runs a mainloop to carry back events, + * messages and timing updates from the PulseAudio server. + * + * In most cases, the PulseAudio API we use communicates with the server and + * processes replies asynchronously. Operations on PA objects that result in + * such communication are protected with a pa_threaded_mainloop_lock() and + * pa_threaded_mainloop_unlock(). These guarantee mutual exclusion with the + * mainloop thread -- when an iteration of the mainloop thread begins, it first + * tries to acquire this lock, and cannot do so if our code also holds that + * lock. + * + * When we need to complete an operation synchronously, we use + * pa_threaded_mainloop_wait() and pa_threaded_mainloop_signal(). These work + * much as pthread conditionals do. pa_threaded_mainloop_wait() is called with + * the mainloop lock held. It releases the lock (thereby allowing the mainloop + * to execute), and waits till one of our callbacks to be executed by the + * mainloop thread calls pa_threaded_mainloop_signal(). At the end of the + * mainloop iteration, the pa_threaded_mainloop_wait() will reacquire the + * mainloop lock and return control to the caller. + */ + /* Store the PA contexts in a hash table to allow easy sharing among * multiple instances of the sink. Keys are $context_name@$server_name * (strings) and values should be GstPulseContext pointers. @@ -1161,7 +1185,7 @@ gst_pulseringbuffer_clear (GstAudioRingBuffer * buf) pa_threaded_mainloop_unlock (mainloop); } -/* called from pulse with the mainloop lock */ +/* called from pulse thread with the mainloop lock */ static void mainloop_enter_defer_cb (pa_mainloop_api * api, void *userdata) { @@ -1248,7 +1272,7 @@ gst_pulseringbuffer_pause (GstAudioRingBuffer * buf) return res; } -/* called from pulse with the mainloop lock */ +/* called from pulse thread with the mainloop lock */ static void mainloop_leave_defer_cb (pa_mainloop_api * api, void *userdata) { diff --git a/ext/pulse/pulsesrc.c b/ext/pulse/pulsesrc.c index 95eb4b7f0..682b92957 100644 --- a/ext/pulse/pulsesrc.c +++ b/ext/pulse/pulsesrc.c @@ -60,6 +60,9 @@ GST_DEBUG_CATEGORY_EXTERN (pulse_debug); #define DEFAULT_MUTE FALSE #define MAX_VOLUME 10.0 +/* See the pulsesink code for notes on how we interact with the PA mainloop + * thread. */ + enum { PROP_0, |