Add side-channel to image worker for early exiting

This commit is contained in:
Héctor Ramón Jiménez 2025-10-26 20:23:26 +01:00
parent 44cfb27e41
commit b408961d77
No known key found for this signature in database
GPG key ID: 7CC46565708259A7

View file

@ -19,6 +19,8 @@ pub struct Cache {
#[cfg(feature = "image")] #[cfg(feature = "image")]
jobs: mpsc::SyncSender<Job>, jobs: mpsc::SyncSender<Job>,
#[cfg(feature = "image")] #[cfg(feature = "image")]
quit: mpsc::SyncSender<()>,
#[cfg(feature = "image")]
work: mpsc::Receiver<Work>, work: mpsc::Receiver<Work>,
#[cfg(all(feature = "image", not(target_arch = "wasm32")))] #[cfg(all(feature = "image", not(target_arch = "wasm32")))]
worker_: Option<std::thread::JoinHandle<()>>, worker_: Option<std::thread::JoinHandle<()>>,
@ -33,7 +35,7 @@ impl Cache {
_shell: &Shell, _shell: &Shell,
) -> Self { ) -> Self {
#[cfg(all(feature = "image", not(target_arch = "wasm32")))] #[cfg(all(feature = "image", not(target_arch = "wasm32")))]
let (worker, jobs, work) = let (worker, jobs, quit, work) =
Worker::new(device, _queue, backend, layout.clone(), _shell); Worker::new(device, _queue, backend, layout.clone(), _shell);
#[cfg(all(feature = "image", target_arch = "wasm32"))] #[cfg(all(feature = "image", target_arch = "wasm32"))]
@ -55,6 +57,8 @@ impl Cache {
#[cfg(feature = "image")] #[cfg(feature = "image")]
jobs, jobs,
#[cfg(feature = "image")] #[cfg(feature = "image")]
quit,
#[cfg(feature = "image")]
work, work,
#[cfg(all(feature = "image", not(target_arch = "wasm32")))] #[cfg(all(feature = "image", not(target_arch = "wasm32")))]
worker_: Some(handle), worker_: Some(handle),
@ -277,11 +281,8 @@ impl Cache {
#[cfg(all(feature = "image", not(target_arch = "wasm32")))] #[cfg(all(feature = "image", not(target_arch = "wasm32")))]
impl Drop for Cache { impl Drop for Cache {
fn drop(&mut self) { fn drop(&mut self) {
// Stop worker gracefully let _ = self.quit.try_send(());
let (sender, _) = mpsc::sync_channel(1); let _ = self.jobs.send(Job::Quit);
self.jobs = sender.clone();
self.raster.jobs = sender;
let _ = self.worker_.take().unwrap().join(); let _ = self.worker_.take().unwrap().join();
} }
} }
@ -333,6 +334,7 @@ enum Job {
height: u32, height: u32,
}, },
Drop(Arc<wgpu::BindGroup>), Drop(Arc<wgpu::BindGroup>),
Quit,
} }
#[cfg(feature = "image")] #[cfg(feature = "image")]
@ -358,6 +360,7 @@ struct Worker {
belt: wgpu::util::StagingBelt, belt: wgpu::util::StagingBelt,
jobs: mpsc::Receiver<Job>, jobs: mpsc::Receiver<Job>,
output: mpsc::SyncSender<Work>, output: mpsc::SyncSender<Work>,
quit: mpsc::Receiver<()>,
} }
#[cfg(all(feature = "image", not(target_arch = "wasm32")))] #[cfg(all(feature = "image", not(target_arch = "wasm32")))]
@ -368,8 +371,14 @@ impl Worker {
backend: wgpu::Backend, backend: wgpu::Backend,
texture_layout: wgpu::BindGroupLayout, texture_layout: wgpu::BindGroupLayout,
shell: &Shell, shell: &Shell,
) -> (Self, mpsc::SyncSender<Job>, mpsc::Receiver<Work>) { ) -> (
Self,
mpsc::SyncSender<Job>,
mpsc::SyncSender<()>,
mpsc::Receiver<Work>,
) {
let (jobs_sender, jobs_receiver) = mpsc::sync_channel(1_000); let (jobs_sender, jobs_receiver) = mpsc::sync_channel(1_000);
let (quit_sender, quit_receiver) = mpsc::sync_channel(1);
let (work_sender, work_receiver) = mpsc::sync_channel(1_000); let (work_sender, work_receiver) = mpsc::sync_channel(1_000);
( (
@ -382,14 +391,24 @@ impl Worker {
belt: wgpu::util::StagingBelt::new(4 * 1024 * 1024), belt: wgpu::util::StagingBelt::new(4 * 1024 * 1024),
jobs: jobs_receiver, jobs: jobs_receiver,
output: work_sender, output: work_sender,
quit: quit_receiver,
}, },
jobs_sender, jobs_sender,
quit_sender,
work_receiver, work_receiver,
) )
} }
fn run(mut self) { fn run(mut self) {
while let Ok(job) = self.jobs.recv() { loop {
if self.quit.try_recv().is_ok() {
return;
}
let Ok(job) = self.jobs.recv() else {
return;
};
match job { match job {
Job::Load(handle) => { Job::Load(handle) => {
match crate::graphics::image::load(&handle) { match crate::graphics::image::load(&handle) {
@ -423,6 +442,7 @@ impl Worker {
Job::Drop(bind_group) => { Job::Drop(bind_group) => {
drop(bind_group); drop(bind_group);
} }
Job::Quit => return,
} }
} }
} }