Non Blocking Channel Operations in Rust

Rust provides a similar concept to Go’s channels called “channels” as well. However, the implementation and usage are slightly different. Let’s see how we can implement non-blocking channel operations in Rust.

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

fn main() {
    let (tx, rx) = mpsc::channel();
    let (tx_signal, rx_signal) = mpsc::channel();

    // Here's a non-blocking receive. If a value is
    // available on `rx` then `try_recv()` will return
    // Ok with that value. If not, it will return an Err.
    match rx.try_recv() {
        Ok(msg) => println!("received message {}", msg),
        Err(_) => println!("no message received"),
    }

    // A non-blocking send works similarly. Here `msg`
    // is sent to the `tx` channel using `try_send()`.
    // If the channel is full or there's no receiver,
    // it will return an Err.
    let msg = "hi";
    match tx.try_send(msg) {
        Ok(_) => println!("sent message {}", msg),
        Err(_) => println!("no message sent"),
    }

    // We can use multiple `match` arms to implement
    // a multi-way non-blocking select. Here we attempt
    // non-blocking receives on both `rx` and `rx_signal`.
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(100));
        tx.send("hello").unwrap();
    });

    thread::spawn(move || {
        thread::sleep(Duration::from_millis(50));
        tx_signal.send(true).unwrap();
    });

    loop {
        match rx.try_recv() {
            Ok(msg) => {
                println!("received message {}", msg);
                break;
            }
            Err(_) => {}
        }

        match rx_signal.try_recv() {
            Ok(sig) => {
                println!("received signal {}", sig);
                break;
            }
            Err(_) => {}
        }

        println!("no activity");
        thread::sleep(Duration::from_millis(10));
    }
}

To run the program:

$ cargo run
no message received
no message sent
no activity
no activity
no activity
received signal true

In this Rust example, we use the mpsc (multi-producer, single-consumer) channel from the standard library. The try_recv() and try_send() methods provide non-blocking operations on channels.

We simulate the multi-way select by using a loop and attempting to receive from multiple channels. This isn’t as elegant as Go’s select statement, but it achieves similar functionality.

Note that Rust’s channels are a bit different from Go’s. They are multi-producer but single-consumer, and they don’t have a built-in select mechanism. However, there are crates available that provide more Go-like channel operations if needed.