/// TODO: the code below will deadlock because it's using std's channels, /// which are not async-aware. /// Rewrite it to use `tokio`'s channels primitive (you'll have to touch /// the testing code too, yes). /// /// Can you understand the sequence of events that can lead to a deadlock? use std::sync::mpsc; pub struct Message { payload: String, response_channel: mpsc::Sender, } /// Replies with `pong` to any message it receives, setting up a new /// channel to continue communicating with the caller. pub async fn pong(mut receiver: mpsc::Receiver) { loop { if let Ok(msg) = receiver.recv() { println!("Pong received: {}", msg.payload); let (sender, new_receiver) = mpsc::channel(); msg.response_channel .send(Message { payload: "pong".into(), response_channel: sender, }) .unwrap(); receiver = new_receiver; } } } #[cfg(test)] mod tests { use crate::{pong, Message}; use std::sync::mpsc; #[tokio::test] async fn ping() { let (sender, receiver) = mpsc::channel(); let (response_sender, response_receiver) = mpsc::channel(); sender .send(Message { payload: "pong".into(), response_channel: response_sender, }) .unwrap(); tokio::spawn(pong(receiver)); let answer = response_receiver.recv().unwrap().payload; assert_eq!(answer, "pong"); } }