grafix_toolbox/kit/opengl/context/
offhand.rs1use super::{window::*, *};
2use crate::sync::*;
3
4pub struct Offhand<O> {
5 handle: Option<JoinHandle<()>>,
6 rx: Receiver<(O, Fence)>,
7}
8impl<O: SendS> Offhand<O> {
9 pub fn new<I: SendS>(w: &mut impl Window, depth: usize, process: impl SendS + Fn(I) -> O) -> (Sender<I>, Self) {
10 Self::from_fn(w, depth, move |data_rx, res_sn| {
11 while let Ok(msg) = data_rx.recv() {
12 let res = process(msg);
13 res_sn.send((res, Fence::new())).warn();
14 }
15 })
16 }
17 pub fn from_fn<I: SendS>(w: &mut impl Window, depth: usize, process: impl SendS + Fn(Receiver<I>, Sender<(O, Fence)>)) -> (Sender<I>, Self) {
18 let (data_sn, data_rx) = chan::bounded::<I>(depth);
19 let (res_sn, rx) = chan::bounded::<(O, Fence)>(depth);
20
21 let init = w.gl_ctx_maker();
22 let handle = thread::Builder::new()
23 .name("gl_offhand".into())
24 .spawn(move || {
25 let _ctx = init();
26 process(data_rx, res_sn)
27 })
28 .explain_err(|| "Cannot spawn offhand")
29 .fail()
30 .pipe(Some);
31
32 (data_sn, Self { handle, rx })
33 }
34 pub fn recv(&self) -> Option<OffhandRes<O>> {
35 self.rx.recv().ok().map(OffhandRes)
36 }
37 pub fn try_recv(&self) -> Option<OffhandRes<O>> {
38 self.rx.try_recv().ok().map(OffhandRes)
39 }
40}
41impl<O> Drop for Offhand<O> {
42 fn drop(&mut self) {
43 self.handle.take().valid().join_fail(|| format!("GL Offhand<{}> panicked", type_name::<O>()));
44 }
45}
46
47pub struct OffhandRes<O>((O, Fence));
48impl<O> OffhandRes<O> {
49 pub fn wait(self) -> O {
50 let (r, f) = self.0;
51 f.Block();
52 r
53 }
54}