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.