Bosh
Bosh

Reputation: 8738

Read from a channel or timeout?

With Rust 1.9, I'd like to read from a mpsc::channel or timeout. Is there a clear idiom to make this work? I've seen the unstable approach described in mpsc::Select but this Github discussion suggests it is not a robust approach. Is there a better-recommended way for me to achieve receive-or-timeout semantics?

Upvotes: 14

Views: 3540

Answers (3)

Gera Garza
Gera Garza

Reputation: 161

I was able to get something working using the standard lib.

use std::sync::mpsc::channel;
use std::thread;
use std::time::{Duration, Instant};
use std::sync::mpsc::TryRecvError;


fn main() {
    let (send, recv) = channel();

    thread::spawn(move || {
        send.send("Hello world!").unwrap();
        thread::sleep(Duration::from_secs(1)); // block for two seconds
        send.send("Delayed").unwrap();
    });

    println!("{}", recv.recv().unwrap()); // Received immediately
    println!("Waiting...");

    let mut resolved: bool = false;
    let mut result: Result<&str, TryRecvError> = Ok("Null");

    let now = Instant::now();
    let timeout: u64= 2;

    while !resolved {
        result = recv.try_recv();
        resolved = !result.is_err();
        if now.elapsed().as_secs() as u64 > timeout {
            break;
        }
    }

    if result.is_ok(){
        println!("Results: {:?}", result.unwrap());
    }

    println!("Time elapsed: {}", now.elapsed().as_secs());
    println!("Resolved: {}", resolved.to_string());
}

This will spin for timeout seconds and will result in either the received value or an Err Result.

Upvotes: 1

tez
tez

Reputation: 5300

Rust 1.12 introduced Receiver::recv_timeout:

use std::sync::mpsc::channel;
use std::time::Duration;

fn main() {
    let (.., rx) = channel::<bool>();
    let timeout = Duration::new(3, 0);

    println!("start recv");
    let _ = rx.recv_timeout(timeout);
    println!("done!");
}

Upvotes: 11

Shepmaster
Shepmaster

Reputation: 430841

I don't know how you'd do it with the standard library channels, but the chan crate provides a chan_select! macro:

#[macro_use]
extern crate chan;

use std::time::Duration;

fn main() {
    let (_never_sends, never_receives) = chan::sync::<bool>(1);
    let timeout = chan::after(Duration::from_millis(50));

    chan_select! {
        timeout.recv() => {
            println!("timed out!");
        },
        never_receives.recv() => {
            println!("Shouldn't have a value!");
        },
    }
}

Upvotes: 5

Related Questions