如何在不阻塞的情况下查看频道并且仍然能够检测挂断?

iag*_*ito 6 channel nonblocking peek rust

根据Rust 结尾的.try_iter()方法的文档,我知道这个迭代器要么产生“None”:Receiverstd::mpsc::channel

  • 当通道中没有数据时
  • 或者当频道的另一端挂断时。

就我而言,我想peek进入通道,而不阻塞,以便确定是否:

  • 有数据(但没有消耗它),或者
  • 没有数据,或者
  • 频道已挂断。

问题是如果我..

match my_receiver.try_iter().peekable().peek() {
    Some(data) => {/* there is data */}
    None => {/* there is no data, but there may be later.. or maybe not, because the channel has maybe hung up, I can't tell! */}
}
Run Code Online (Sandbox Code Playgroud)

..我只能区分两种情况。

receiver当存在数据时,如何才能查看通道的末尾并区分这三种可能的结果,而不阻塞或消耗数据?

har*_*mic 5

try_iter()方法返回一个丢弃Error值的迭代器,因此您无法区分不同的情况。

您可以创建自己的迭代器,它会迭代而Result不是丢弃错误值:

pub struct TryIterResult<'a, T: 'a> {
    rx: &'a Receiver<T>,
}

pub fn try_iter_result<'a, T>(rx: &'a Receiver<T>) -> TryIterResult<'a, T> {
    TryIterResult { rx: &rx }
}

impl<'a, T> Iterator for TryIterResult<'a, T> {
    type Item = Result<T, TryRecvError>;

    fn next(&mut self) -> Option<Result<T, TryRecvError>> {
        match self.rx.try_recv() {
            Ok(data) => Some(Ok(data)),
            Err(TryRecvError::Empty) => Some(Err(TryRecvError::Empty)),
            Err(TryRecvError::Disconnected) => None
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您将能够获得一个可查看的迭代器,它将返回三个可能的条件:

match try_iter_result(my_receiver).peekable().peek() {
    Some(Ok(data)) =>{ /* there is data */},
    Some(Err(_)) => { /* nothing available right now */ },
    None => {/* disconnected */}
}    
Run Code Online (Sandbox Code Playgroud)