|
libfunnel
|
This documentation uses the following terms to describe the lifetime of API objects:
For input arguments (the default if not specified):
user : The object is owned by the caller and borrowed by libfunnel object user. The caller must release user before it releases this object.For output arguments:
parent : The object is owned by the parent object parent. Once ownership of parent is transferred back to libfunnel, the borrowed object becomes invalid and may no longer be used.parent. The object must be released by the caller before parent is released.If an API call returns an error, then any ownership changes implied by the arguments do not take effect. For example, if funnel_buffer_enqueue() fails, that means there was a usage error and the buffer is still owned by the caller.
libfunnel does not use thread-local state. This means that you are free to call libfunnel functions for multiple threads, as long as the calls meet the synchronization requirements. The baseline synchronization (thread safety) requirements for libfunnel objects follow from the lifetime definitions:
If you perform these operations in different threads, you must make sure that not only they do not overlap, but that appropriate memory sychrnonization is observed (memory barriers, etc.). If you are using standard OS synchronization mechanisms like mutexes, you do not need to worry about this, as those APIs take care of it for you.
In addition, libfunnel functions are assigned these two synchronization categories:
Note that these requirements do not override the lifetime requirements. For example, you cannot destroy an object concurrently with a call to a function that borrows it, even if the latter call is marked with internal synchronization.
The general design of libfunnel synchronization is roughly that:
Internally, libfunnel uses a single PipeWire thread loop per funnel_ctx, and synchronization happens using a context-global lock. Therefore, if your application has multiple completely independent streams that have no relation to each other and are managed by different threads, it may be more efficient to create a whole new funnel_ctx for each thread, and therefore have independent PipeWire daemon connections and thread loops. This is particularly relevant if you are using FUNNEL_SYNCHRONOUS mode, since in that mode the PipeWire processing thread is completely blocked while any stream has a buffer dequeued.