From 7ba227a1b6e985dcb537b95c398b7d459b686b8d Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Wed, 17 Jul 2024 09:24:40 -0400 Subject: [PATCH] Expand the thread-doc to clarify and expand realtime Summarizing the conversation in discussion #414, this PR adds a more complete description of when the realtime constraint must be met, by which party, and how it interacts with the thread safe tag. --- include/clap/ext/thread-check.h | 43 +++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/include/clap/ext/thread-check.h b/include/clap/ext/thread-check.h index 7b68e1b0..255242d8 100644 --- a/include/clap/ext/thread-check.h +++ b/include/clap/ext/thread-check.h @@ -17,23 +17,40 @@ extern "C" { /// This will be the same OS thread throughout the lifetime of the plug-in. /// On macOS and Windows, this must be the thread on which gui and timer events are received /// (i.e., the main thread of the program). -/// It isn't a realtime thread, yet this thread needs to respond fast enough to user interaction, -/// so it is recommended to run long and expensive tasks such as preset indexing or asset loading -/// in dedicated background threads. +/// It isn't a realtime thread, yet this thread needs to respond fast enough to allow user interaction, +/// so it is strongly recommended plugins run long,and expensive or blocking tasks such as preset indexing +/// or asset loading in dedicated background threads started by the plugin. /// /// audio-thread: -/// This thread is used for realtime audio processing. Its execution should be as deterministic -/// as possible to meet the audio interface's deadline (can be <1ms). In other words, there is a -/// known set of operations that should be avoided: malloc() and free(), mutexes (spin mutexes -/// are worse), I/O, waiting, ... -/// The audio-thread is something symbolic, there isn't one OS thread that remains the -/// audio-thread for the plugin lifetime. As you may guess, the host is likely to have a +/// This thread can be used for realtime audio processing. Its execution should be as deterministic +/// as possible to meet the audio interface's deadline (can be <1ms). There are a +/// known set of operations that should be avoided: malloc() and free(), contended locks and mutexes, +/// I/O, waiting, and so forth. +/// +/// The audio-thread is symbolic, there isn't one OS thread that remains the +/// audio-thread for the plugin lifetime. A host is may opt to have a /// thread pool and the plugin.process() call may be scheduled on different OS threads over time. -/// The most important thing is that there can't be two audio-threads at the same time. All the -/// functions marked with [audio-thread] **ARE NOT CONCURRENT**. The host may mark any OS thread, +/// However, the host must guarantee that single plugin instance will not be two audio-threads +/// at the same time. +/// +/// Functions marked with [audio-thread] **ARE NOT CONCURRENT**. The host may mark any OS thread, /// including the main-thread as the audio-thread, as long as it can guarantee that only one OS -/// thread is the audio-thread at a time. The audio-thread can be seen as a concurrency guard for -/// all functions marked with [audio-thread]. +/// thread is the audio-thread at a time in a plugin instance. The audio-thread can be seen as a +/// concurrency guard for all functions marked with [audio-thread]. +/// +/// The real-time constraint on the [audio-thread] interacts closely with the render extension. +/// If a plugin doesn't implement render, then that plugin must have all [audio-thread] functions +/// meet the real time standard. If the plugin does implement render, and returns true when +/// render mode is set to real-time or if the plugin advertises a hard realtime requirement, it +/// must implement realtime constraints. Host provided [audio-thread] functions can be called +/// from a plugin on the audio thread and must also therefore either meet the real-time constraint, +/// not run plugins which advertise a hard realtime constraint via render or don't implement render, +/// or expect potentially inconsistent rendering and performance from plugins when they re-enter the host. +/// +/// Clap also tags some functions as [thread-safe]. Functions tagged as [thread-safe] can be called from +/// any thread unless explicitly counter-indicated (for instance [thread-safe, !audio-thread]) and may +/// be called concurrently. Since a [thread-safe] function may be called from the [audio-thread] unless +/// explicitly counter-indicated, it must also meet the realtime constraints as describes above. // This interface is useful to do runtime checks and make // sure that the functions are called on the correct threads.