use std::{
io::{self, Read},
time::Duration,
};
use crossbeam_channel::Receiver;
use super::blocking::Blocking;
#[derive(Debug)]
pub struct Wait2<R1, R2> {
recv: Receiver<(usize, io::Result<Option<u8>>)>,
b1: Blocking<R1>,
b2: Blocking<R2>,
timeout: Duration,
}
#[derive(Debug)]
pub enum Recv {
R1(io::Result<Option<u8>>),
R2(io::Result<Option<u8>>),
Timeout,
}
impl<R1, R2> Wait2<R1, R2> {
pub fn new(r1: R1, r2: R2) -> Self
where
R1: Send + Read + 'static,
R2: Send + Read + 'static,
{
let (sndr, recv) = crossbeam_channel::unbounded();
let b1 = Blocking::new(0, r1, sndr.clone());
let b2 = Blocking::new(1, r2, sndr);
Self {
b1,
b2,
recv,
timeout: Duration::from_secs(5),
}
}
pub fn join(self) -> std::thread::Result<()> {
self.b1.join()?;
self.b2.join()?;
Ok(())
}
pub fn recv(&mut self) -> Result<Recv, crossbeam_channel::RecvError> {
match self.recv.recv_timeout(self.timeout) {
Ok((id, result)) => match id {
0 => Ok(Recv::R1(result)),
1 => Ok(Recv::R2(result)),
_ => unreachable!(),
},
Err(err) => {
if err.is_timeout() {
Ok(Recv::Timeout)
} else {
Err(crossbeam_channel::RecvError)
}
}
}
}
}