Skip to content

Commit

Permalink
Enable garbage collector thread only for online AudioContext
Browse files Browse the repository at this point in the history
Fixes #367
  • Loading branch information
orottier committed Oct 19, 2023
1 parent 05a67ac commit 3d721a0
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 30 deletions.
2 changes: 0 additions & 2 deletions src/context/offline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ impl OfflineAudioContext {
number_of_channels,
receiver,
frames_played_clone,
None,
None,
);

// first, setup the base audio context
Expand Down
12 changes: 6 additions & 6 deletions src/io/cpal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,14 @@ impl AudioBackendManager for CpalBackend {
// shared atomic to report output latency to the control thread
let output_latency = Arc::new(AtomicF64::new(0.));

let renderer = RenderThread::new(
let mut renderer = RenderThread::new(
sample_rate,
preferred_config.channels as usize,
ctrl_msg_recv.clone(),
Arc::clone(&frames_played),
Some(load_value_send.clone()),
Some(event_send.clone()),
);
renderer.set_event_channels(load_value_send.clone(), event_send.clone());
renderer.spawn_garbage_collector_thread();

log::debug!(
"Attempt output stream with preferred config: {:?}",
Expand Down Expand Up @@ -227,14 +227,14 @@ impl AudioBackendManager for CpalBackend {
&supported_config
);

let renderer = RenderThread::new(
let mut renderer = RenderThread::new(
sample_rate,
supported_config.channels as usize,
ctrl_msg_recv,
frames_played,
Some(load_value_send),
Some(event_send),
);
renderer.set_event_channels(load_value_send, event_send);
renderer.spawn_garbage_collector_thread();

let spawned = spawn_output_stream(
&device,
Expand Down
6 changes: 3 additions & 3 deletions src/io/cubeb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,14 @@ impl AudioBackendManager for CubebBackend {
_ => cubeb::ChannelLayout::UNDEFINED, // TODO, does this work?
};

let renderer = RenderThread::new(
let mut renderer = RenderThread::new(
sample_rate,
number_of_channels,
ctrl_msg_recv,
frames_played,
Some(load_value_send),
Some(event_send),
);
renderer.set_event_channels(load_value_send, event_send);
renderer.spawn_garbage_collector_thread();

let params = cubeb::StreamParamsBuilder::new()
.format(cubeb::SampleFormat::Float32NE) // use float (native endian)
Expand Down
12 changes: 4 additions & 8 deletions src/io/none.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,10 @@ impl AudioBackendManager for NoneBackend {
event_send,
} = render_thread_init;

let render_thread = RenderThread::new(
sample_rate,
MAX_CHANNELS,
ctrl_msg_recv,
frames_played,
Some(load_value_send),
Some(event_send),
);
let mut render_thread =
RenderThread::new(sample_rate, MAX_CHANNELS, ctrl_msg_recv, frames_played);
render_thread.set_event_channels(load_value_send, event_send);
render_thread.spawn_garbage_collector_thread();

// Use a bounded channel for real-time safety. A maximum of 32 control messages (resume,
// suspend, ..) will be handled per render quantum. The control thread will block when the
Expand Down
38 changes: 27 additions & 11 deletions src/render/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub(crate) struct RenderThread {
buffer_offset: Option<(usize, AudioRenderQuantum)>,
load_value_sender: Option<Sender<AudioRenderCapacityLoad>>,
event_sender: Option<Sender<EventDispatch>>,
garbage_collector: llq::Producer<Box<dyn Any + Send>>,
garbage_collector: Option<llq::Producer<Box<dyn Any + Send>>>,
}

// SAFETY:
Expand All @@ -52,21 +52,34 @@ impl RenderThread {
number_of_channels: usize,
receiver: Receiver<ControlMessage>,
frames_played: Arc<AtomicU64>,
load_value_sender: Option<Sender<AudioRenderCapacityLoad>>,
event_sender: Option<Sender<EventDispatch>>,
) -> Self {
let (gc_producer, gc_consumer) = llq::Queue::new().split();
spawn_garbage_collector_thread(gc_consumer);
Self {
graph: None,
sample_rate,
number_of_channels,
frames_played,
receiver: Some(receiver),
buffer_offset: None,
load_value_sender,
event_sender,
garbage_collector: gc_producer,
load_value_sender: None,
event_sender: None,
garbage_collector: None,
}
}

pub(crate) fn set_event_channels(
&mut self,
load_value_sender: Sender<AudioRenderCapacityLoad>,
event_sender: Sender<EventDispatch>,
) {
self.load_value_sender = Some(load_value_sender);
self.event_sender = Some(event_sender);
}

pub(crate) fn spawn_garbage_collector_thread(&mut self) {
if self.garbage_collector.is_none() {
let (gc_producer, gc_consumer) = llq::Queue::new().split();
spawn_garbage_collector_thread(gc_consumer);
self.garbage_collector = Some(gc_producer);
}
}

Expand Down Expand Up @@ -129,7 +142,9 @@ impl RenderThread {
}
NodeMessage { id, mut msg } => {
self.graph.as_mut().unwrap().route_message(id, msg.as_mut());
self.garbage_collector.push(msg);
if let Some(gc) = self.garbage_collector.as_mut() {
gc.push(msg)
}
}
}
}
Expand Down Expand Up @@ -301,8 +316,9 @@ impl RenderThread {

impl Drop for RenderThread {
fn drop(&mut self) {
self.garbage_collector
.push(llq::Node::new(Box::new(TerminateGarbageCollectorThread)));
if let Some(gc) = self.garbage_collector.as_mut() {
gc.push(llq::Node::new(Box::new(TerminateGarbageCollectorThread)))
}
log::info!("Audio render thread has been dropped");
}
}
Expand Down

0 comments on commit 3d721a0

Please sign in to comment.