From cf534791fb3bcae95285151ea8ca164ee0de0f8e Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Sun, 27 Oct 2024 21:18:16 +0100 Subject: [PATCH] Exercises 8-{02,03,04} --- exercises/08_futures/02_spawn/src/lib.rs | 18 +++++++++++++++++- exercises/08_futures/03_runtime/src/lib.rs | 20 ++++++++++++++++++-- exercises/08_futures/04_future/src/lib.rs | 6 ++++-- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/exercises/08_futures/02_spawn/src/lib.rs b/exercises/08_futures/02_spawn/src/lib.rs index 9e00f36..6f56780 100644 --- a/exercises/08_futures/02_spawn/src/lib.rs +++ b/exercises/08_futures/02_spawn/src/lib.rs @@ -1,10 +1,26 @@ use tokio::net::TcpListener; +async fn handle_tcp_listener(listener: TcpListener) -> Result<(), anyhow::Error> { + loop { + let (mut stream, _) = listener.accept().await?; + tokio::spawn(async move { + let (mut reader, mut writer) = stream.split(); + tokio::io::copy(&mut reader, &mut writer).await.unwrap(); + }); + } +} + // TODO: write an echo server that accepts TCP connections on two listeners, concurrently. // Multiple connections (on the same listeners) should be processed concurrently. // The received data should be echoed back to the client. pub async fn echoes(first: TcpListener, second: TcpListener) -> Result<(), anyhow::Error> { - todo!() + let handle1 = tokio::spawn(handle_tcp_listener(first)); + let handle2 = tokio::spawn(handle_tcp_listener(second)); + + let (outcome1, outcome2) = tokio::join!(handle1, handle2); + outcome1??; + outcome2??; + Ok(()) } #[cfg(test)] diff --git a/exercises/08_futures/03_runtime/src/lib.rs b/exercises/08_futures/03_runtime/src/lib.rs index 087ddc0..5a8e0b8 100644 --- a/exercises/08_futures/03_runtime/src/lib.rs +++ b/exercises/08_futures/03_runtime/src/lib.rs @@ -1,7 +1,7 @@ // TODO: Implement the `fixed_reply` function. It should accept two `TcpListener` instances, // accept connections on both of them concurrently, and always reply to clients by sending // the `Display` representation of the `reply` argument as a response. -use std::fmt::Display; +use std::{fmt::Display, sync::Arc}; use tokio::io::AsyncWriteExt; use tokio::net::TcpListener; @@ -10,7 +10,23 @@ where // `T` cannot be cloned. How do you share it between the two server tasks? T: Display + Send + Sync + 'static, { - todo!() + let reply = Arc::new(reply); + let handle1 = tokio::spawn(handle_listener(first, reply.clone())); + let handle2 = tokio::spawn(handle_listener(second, reply)); + let _ = tokio::join!(handle1, handle2); +} + +async fn handle_listener(listener: TcpListener, reply: Arc) +where + T: Display + Send + Sync + 'static, +{ + loop { + let (mut stream, _) = listener.accept().await.unwrap(); + stream + .write_all(reply.to_string().as_bytes()) + .await + .unwrap(); + } } #[cfg(test)] diff --git a/exercises/08_futures/04_future/src/lib.rs b/exercises/08_futures/04_future/src/lib.rs index 8dc1c96..4980f8d 100644 --- a/exercises/08_futures/04_future/src/lib.rs +++ b/exercises/08_futures/04_future/src/lib.rs @@ -10,7 +10,9 @@ fn spawner() { } async fn example() { - let non_send = Rc::new(1); + { + let non_send = Rc::new(1); + println!("{}", non_send); + } yield_now().await; - println!("{}", non_send); } -- 2.45.2