use super::{window::*, *}; use crate::sync::*; pub struct Offhand { handle: Option>, rx: Receiver<(O, Fence)>, } impl Offhand { pub fn new(w: &mut Window, depth: usize, process: impl SendStat + Fn(I) -> O) -> (Sender, Self) { Self::from_fn(w, depth, move |data_rx, res_sn| { while let Ok(msg) = data_rx.recv() { let res = process(msg); res_sn.send((res, Fence::new())).warn(); } }) } pub fn from_fn(w: &mut Window, depth: usize, process: impl SendStat + Fn(Receiver, Sender<(O, Fence)>)) -> (Sender, Self) { let (data_sn, data_rx) = chan::bounded::(depth); let (res_sn, res_rx) = chan::bounded::<(O, Fence)>(depth); let handle = w.spawn_offhand_gl(move || process(data_rx, res_sn)); let (handle, rx) = (Some(handle), res_rx); (data_sn, Self { handle, rx }) } pub fn recv(&self) -> Option> { self.rx.recv().ok().map(|r| OffhandRes(r)) } pub fn try_recv(&self) -> Option> { self.rx.try_recv().ok().map(|r| OffhandRes(r)) } } impl Drop for Offhand { fn drop(&mut self) { self.handle.take().valid().join().valid(); } } pub struct OffhandRes((O, Fence)); impl OffhandRes { pub fn wait(self) -> O { let (r, f) = self.0; f.Block(); r } }