#include <processor_hotswap_slot.hpp>
◆ ProcessorHotSwapSlot() [1/2]
| pulp::format::reload::ProcessorHotSwapSlot::ProcessorHotSwapSlot |
( |
| ) |
|
|
default |
◆ ProcessorHotSwapSlot() [2/2]
| pulp::format::reload::ProcessorHotSwapSlot::ProcessorHotSwapSlot |
( |
std::unique_ptr< Processor > | initial | ) |
|
|
inlineexplicit |
◆ contention_blocks()
| std::uint64_t pulp::format::reload::ProcessorHotSwapSlot::contention_blocks |
( |
| ) |
const |
|
inline |
Number of blocks that passed through due to swap contention / no active processor (dev metric).
◆ crossfade_active()
| bool pulp::format::reload::ProcessorHotSwapSlot::crossfade_active |
( |
| ) |
const |
|
inline |
True while a crossfade is in progress (a fade-out is rendering).
◆ has_active()
| bool pulp::format::reload::ProcessorHotSwapSlot::has_active |
( |
| ) |
const |
|
inline |
True when a processor is installed. Control-thread/diagnostic use.
◆ prepare_crossfade()
| void pulp::format::reload::ProcessorHotSwapSlot::prepare_crossfade |
( |
std::size_t | max_frames, |
|
|
std::size_t | max_channels ) |
|
inline |
Allocate the scratch the fade-out processor renders into, sized for the worst-case block.
Control thread, off the audio path (called from the host's prepare()). Re-callable (audio stopped); sizes are set exactly to the arguments, not grown — call with the worst-case block.
◆ process()
Audio-thread entry.
Forwards to the active processor under a non-blocking shared lock; on swap contention (or no active processor) it passes the input through to the output for this block and counts it. When a previous processor is fading out (a crossfaded swap), it is rendered in parallel into the scratch buffer and mixed under a smoothstep ramp. Never blocks, allocates, or destroys.
◆ reclaim()
| void pulp::format::reload::ProcessorHotSwapSlot::reclaim |
( |
| ) |
|
|
inline |
Control-thread reclaim of a completed fade-out.
Frees the retired processor on THIS (control) thread under the writer lock — which proves no audio reader is inside it. Call periodically (e.g. from the shell's watcher tick). No-op when nothing is pending or a fade is still running.
◆ reprepare_active()
| void pulp::format::reload::ProcessorHotSwapSlot::reprepare_active |
( |
const PrepareContext & | ctx | ) |
|
|
inline |
Control-thread re-prepare of the live processor (e.g.
a host sample-rate change). Takes the writer lock — the same one swap() uses — so it cannot race a reader inside process(). No-op when no processor is installed. Call only while audio is stopped, like prepare(): the writer lock guarantees mutual exclusion with process(), not that prepare() (which may allocate) is realtime.
◆ set_crossfade_curve()
| void pulp::format::reload::ProcessorHotSwapSlot::set_crossfade_curve |
( |
CrossfadeCurve | curve | ) |
|
|
inline |
Select the crossfade amplitude law (default Smoothstep = equal-gain).
Control thread, before swaps. Takes effect on the next swap; changing it mid-fade is allowed (the running fade keeps its ramp position, only the gain mapping changes) but not typical.
◆ set_crossfade_samples()
| void pulp::format::reload::ProcessorHotSwapSlot::set_crossfade_samples |
( |
std::size_t | samples | ) |
|
|
inline |
Set the crossfade length in samples (0 = instantaneous swaps; the default).
Control thread, before swaps. Crossfading also requires prepare_crossfade() to have allocated the parallel-render scratch.
◆ swap()
| std::unique_ptr< Processor > pulp::format::reload::ProcessorHotSwapSlot::swap |
( |
std::unique_ptr< Processor > | next | ) |
|
|
inlinenodiscard |
Control-thread swap.
Without a crossfade configured this installs next and RETURNS the displaced instance for the caller to destroy (on the control thread) — acquiring the writer lock proves no audio reader is inside the old instance. With a crossfade configured (and scratch prepared) it instead RETAINS the displaced instance as the fading-out processor, returns nullptr, and the slot reclaims it later (reclaim() / the next swap() / the destructor). The very first install (no prior active processor) never fades — there is nothing to fade from.
◆ with_active()
template<class Fn>
| auto pulp::format::reload::ProcessorHotSwapSlot::with_active |
( |
Fn && | fn | ) |
const->decltype(fn(std::declval< Processor & >())) |
|
inline |
Invoke fn with the ACTIVE processor under the shared lock, returning its result (or a default-constructed result when no processor is installed).
Control / UI thread only — fn may allocate (e.g. build a view); it runs concurrently with the audio thread's process() (also a shared reader) and only blocks a swap, which is rare. Kept as a template so the slot needs no dependency on whatever fn touches (e.g. pulp::view); the caller instantiates it where those types are complete.
Lifetime note for view-building callers: the processor passed to fn is the one live RIGHT NOW. If it is later hot-swapped out and destroyed, a view that captured it would dangle — so a caller that keeps the editor across reloads must REBUILD on each swap (see ReloadableShell::set_on_reloaded), or have the logic return a self-contained view.
Concurrency contract: fn runs concurrently with the audio thread's process() on the SAME processor (both shared readers). fn must therefore only READ — a create_view() that races a member process() mutates would be a data race. (Building a self-contained view that touches no mutable DSP state is fine.) Note too that while fn holds the shared lock, a swap waiting on the writer lock makes the audio thread's try-lock fail → one or more passthrough blocks for fn's duration; keep fn off the hot path's critical timing (editor open / post-swap rebuild, not per-block).
The documentation for this class was generated from the following file: