Struct Typed Chain
pub struct TypedChain<S: GraphSample, T: StageTuple<S>> { /* private fields */ }Expand description
Typed, effect-only serial Graph with 1..8 sealed concrete stages.
Record-Vec payload is checked against 4MiB before/after reservation; existing Graph allocations and arbitrary processor-owned storage have separate limits. The internal graph drops before the stable cells, including during unwind. Readonly and stopped-exclusive getters derive from the same cell provenance as callbacks. No references are retained across callback/getter boundaries. Bypass freezes a child but retains its declared latency/tail: audible bypass is not latency compensated. Generated output events and auxiliary buses are rejected; accepted input events use canonical Graph broadcast.
§Audio sessions: prefer the guard
The inherent start_audio() returns a non-Send guard that stops the owner on
drop (reverse stage order) on the starting thread. Prefer it. A forgotten guard
(mem::forget, a leak) is misuse, not valid use: it leaves the audio owner
live exactly like an unpaired manual start (see below), and the guard that
would have stopped it no longer exists.
§Manual Processor hooks are a caller obligation
Processor::start_audio on this chain is the canonical manual hook; it returns
no guard. The caller must pair it with Processor::stop_audio on the thread
that started it before transfer to another thread, deactivate, into_stages
or drop. Unlike the guard, nothing stops a manual owner automatically: the
facade adds no owner-thread cleanup, no thread check at process, and a
manually started chain is Send. While a manual owner (or a forgotten guard)
is live:
prepareandstage_mut_stoppedrefuse withAudioSessionActive;deactivate(inherent andProcessor),into_stagesandDropdo not refuse: they panic through the canonical Graph assertion;Processor::stop_audiocalled on another thread panics and leaves the owner live, so it can still be stopped on the owning thread afterwards;process,reset, getters and bypass flags keep working.
Unwind caveats, with no safeguard claimed. A caught deactivate panic happens
before any state change: the chain stays prepared with the owner live, and the
owner thread can still stop_audio. A panic from into_stages or Drop
destroys the facade while unwinding: the Graph is dropped, then each stage is
dropped exactly once by field drop glue, without stop_audio or
deactivate, and no owners are returned. If that panic happens while the
thread is already unwinding, the second panic aborts the process; the facade
does not prevent that.
§Compile-time exclusions
Unsupported static index:
use ravet_graph::TypedChain;
use ravet_gain::GainProcessor;
let chain = TypedChain::<f32,_>::new((GainProcessor::new(0.).unwrap(),),1,64,0).ok().unwrap();
chain.stage::<1>(); // tuple1 has index0 onlyPositive companion (valid index):
use ravet_graph::TypedChain;
use ravet_gain::GainProcessor;
let chain = TypedChain::<f32,_>::new((GainProcessor::new(0.).unwrap(),),1,64,0).ok().unwrap();
let _ = chain.stage::<0>();A readonly stage borrow excludes set_bypassed:
use ravet_graph::{StageAt,TypedChain};
use ravet_foundation::Processor;
fn overlap<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>) {
let stage=chain.stage::<0>();
chain.set_bypassed::<0>(true);
let _=stage.latency_samples();
}A readonly stage borrow excludes process:
use ravet_graph::{StageAt,TypedChain};
use ravet_foundation::{ProcessBlock,Processor};
fn overlap<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>, block:&mut ProcessBlock<'_,'_,'_,f32>) {
let stage=chain.stage::<0>();
let _=chain.process(block);
let _=stage.latency_samples();
}Positive companion: finish the readonly borrow before mutating or rendering.
use ravet_graph::{StageAt,TypedChain};
use ravet_foundation::{ProcessBlock,Processor};
fn ordered<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>, block:&mut ProcessBlock<'_,'_,'_,f32>) {
let latency=chain.stage::<0>().latency_samples();
chain.set_bypassed::<0>(true);
let _=chain.process(block);
let _=latency;
}A live audio session excludes the stopped mutable getter:
use ravet_graph::{StageAt,TypedChain};
use ravet_foundation::Processor;
fn overlap<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>) {
let session=chain.start_audio().ok().unwrap();
let _=chain.stage_mut_stopped::<0>();
drop(session);
}Positive companion: drop the session first.
use ravet_graph::{StageAt,TypedChain};
fn ordered<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>) {
let session=chain.start_audio().ok().unwrap();
drop(session);
let _=chain.stage_mut_stopped::<0>();
}A live &mut P from the stopped getter excludes process:
use ravet_graph::{StageAt,TypedChain};
use ravet_foundation::{ProcessBlock,Processor};
fn overlap<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>, block:&mut ProcessBlock<'_,'_,'_,f32>) {
let stage=chain.stage_mut_stopped::<0>().ok().unwrap();
let _=chain.process(block);
let _=stage.latency_samples();
}… excludes a second stage borrow:
use ravet_graph::{StageAt,TypedChain};
use ravet_foundation::Processor;
fn overlap<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>) {
let stage=chain.stage_mut_stopped::<0>().ok().unwrap();
let _=chain.stage::<0>();
let _=stage.latency_samples();
}… and excludes prepare:
use ravet_graph::{StageAt,TypedChain};
use ravet_foundation::{ProcessConfig,Processor};
fn overlap<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>, config:ProcessConfig) {
let stage=chain.stage_mut_stopped::<0>().ok().unwrap();
let _=chain.prepare(config);
let _=stage.latency_samples();
}Positive companion: use the exclusive stage, then prepare.
use ravet_graph::{StageAt,TypedChain};
use ravet_foundation::{ProcessConfig,Processor};
fn ordered<T: StageAt<f32,0>>(chain:&mut TypedChain<f32,T>, config:ProcessConfig) {
let stage=chain.stage_mut_stopped::<0>().ok().unwrap();
let _=stage.latency_samples();
let _=chain.prepare(config);
}The chain is Send (for Send stages) but not Sync:
use ravet_graph::TypedChain;
use ravet_gain::GainProcessor;
fn sync<T:Sync>() {}
sync::<TypedChain<f32,(GainProcessor,)>>();use ravet_graph::TypedChain;
use ravet_gain::GainProcessor;
fn send<T:Send>() {}
send::<TypedChain<f32,(GainProcessor,)>>();Implementations§
§impl<S: GraphSample, T: StageTuple<S>> TypedChain<S, T>
impl<S: GraphSample, T: StageTuple<S>> TypedChain<S, T>
pub fn new(
stages: T,
channels: usize,
maximum_frames: usize,
maximum_events: usize,
) -> Result<Self, TypedChainFailure<T>>
pub fn new( stages: T, channels: usize, maximum_frames: usize, maximum_events: usize, ) -> Result<Self, TypedChainFailure<T>>
Admission checks return the original tuple before any processor is moved.
The Graph::new error recovery below is not reachable for at most eight
nodes and 576 connections; it is retained as defensive recovery and has no
dedicated test.
pub fn stage<const I: usize>(&self) -> &<T as StageAt<S, I>>::Processor
pub fn stage<const I: usize>(&self) -> &<T as StageAt<S, I>>::Processor
Borrow a concrete stage. This borrow excludes all rendering and mutation.
pub fn stage_mut_stopped<const I: usize>(
&mut self,
) -> Result<&mut <T as StageAt<S, I>>::Processor, PrepareError>
pub fn stage_mut_stopped<const I: usize>( &mut self, ) -> Result<&mut <T as StageAt<S, I>>::Processor, PrepareError>
Deactivate CONTROL first; successful reprepare is required after mutation.
Refuses (AudioSessionActive) while a manual or forgotten audio owner is live.
pub fn set_bypassed<const I: usize>(&mut self, value: bool)
pub fn is_bypassed<const I: usize>(&self) -> bool
pub fn prepare(&mut self, c: ProcessConfig) -> Result<(), PrepareError>
pub fn prepare(&mut self, c: ProcessConfig) -> Result<(), PrepareError>
Refuses (AudioSessionActive) while a manual or forgotten audio owner is live.
pub fn first_fault(&self) -> Option<GraphStatus>
pub fn first_fault(&self) -> Option<GraphStatus>
Original first executed-node fault, until reset/reprepare/deactivation.
pub fn process(&mut self, b: &mut ProcessBlock<'_, '_, '_, S>) -> GraphStatus
pub fn reset(&mut self)
pub fn try_reset(&mut self) -> Result<(), GraphStatus>
pub fn try_reset(&mut self) -> Result<(), GraphStatus>
Forward refusal through the canonical Graph and retain its node identity.
pub fn deactivate(&mut self)
pub fn deactivate(&mut self)
CONTROL only. Panics (canonical Graph assertion) while a manual or
forgotten audio owner is live; it does not refuse. A caught panic leaves the
chain prepared with the owner live (nothing is changed before the assertion),
so the owner thread can still call Processor::stop_audio.
pub fn latency_samples(&self) -> u32
pub fn tail(&self) -> Tail
pub fn start_audio( &mut self, ) -> Result<TypedChainAudioSession<'_, S, T>, GraphStatus>
pub fn into_stages(self) -> T
pub fn into_stages(self) -> T
CONTROL only. Drop graph/wrappers first, then recover the original tuple.
The Graph is only dropped: nothing calls stop_audio here. With a manual
or forgotten audio owner live this panics inside the Graph drop, each
stage is dropped once during the unwind without stop_audio/deactivate,
and the original tuple is not returned. Stop the owner on its thread first.
Trait Implementations§
§impl<S: GraphSample, T: StageTuple<S>> Processor<S> for TypedChain<S, T>
impl<S: GraphSample, T: StageTuple<S>> Processor<S> for TypedChain<S, T>
§fn start_audio(&mut self) -> Result<(), ProcessError>
fn start_audio(&mut self) -> Result<(), ProcessError>
Manual hook: the caller must call stop_audio on this thread before
transfer, deactivate, into_stages or drop (see the type docs). Failure
maps Fault { error, .. } to that error (a retry on a faulted graph is
NotPrepared); the original first fault remains in first_fault().
§fn stop_audio(&mut self)
fn stop_audio(&mut self)
Must run on the thread that started the manual owner; a different thread panics through the canonical assertion and leaves the owner live.
§fn deactivate(&mut self)
fn deactivate(&mut self)
Panics while a manual audio owner is live (see TypedChain::deactivate).