srs2dge_core/target/
catcher.rs

1use crate::target::Target;
2use std::sync::{
3    atomic::{AtomicBool, Ordering},
4    mpsc::{channel, Receiver},
5    Arc,
6};
7use wgpu::Device;
8
9//
10
11pub struct Catcher {
12    error_receiver: Receiver<String>,
13    error_listening: Arc<AtomicBool>,
14}
15
16//
17
18impl Catcher {
19    pub fn new(device: &Device) -> Self {
20        // error capturing/handling
21        let (error_sender, error_receiver) = channel();
22        let listening = Arc::new(AtomicBool::new(false));
23        let error_listening = listening.clone();
24        device.on_uncaptured_error(move |err| match err {
25            wgpu::Error::OutOfMemory { source } => log::error!("Out of memory: {source}"),
26            wgpu::Error::Validation {
27                source,
28                description,
29            } => {
30                if listening.load(Ordering::SeqCst) {
31                    log::warn!("Handled validation error: {source} {description}");
32                    error_sender.send(description).unwrap();
33                } else {
34                    panic!("Unhandled validation error: {source} {description}")
35                }
36            }
37        });
38
39        Self {
40            error_receiver,
41            error_listening,
42        }
43    }
44
45    pub fn catch_error<T, F: FnOnce(&Target) -> T>(target: &Target, f: F) -> Result<T, String> {
46        let s = &target.catcher;
47        s.error_listening.store(true, Ordering::SeqCst);
48        let result = f(target);
49        s.error_listening.store(false, Ordering::SeqCst);
50
51        if let Ok(err) = s.error_receiver.try_recv() {
52            Err(err)
53        } else {
54            Ok(result)
55        }
56    }
57}