Exercises 8-{02,03,04}
authorGreg Burri <greg.burri@gmail.com>
Sun, 27 Oct 2024 20:18:16 +0000 (21:18 +0100)
committerGreg Burri <greg.burri@gmail.com>
Sun, 27 Oct 2024 20:18:16 +0000 (21:18 +0100)
exercises/08_futures/02_spawn/src/lib.rs
exercises/08_futures/03_runtime/src/lib.rs
exercises/08_futures/04_future/src/lib.rs

index 9e00f36..6f56780 100644 (file)
@@ -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)]
index 087ddc0..5a8e0b8 100644 (file)
@@ -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<T>(listener: TcpListener, reply: Arc<T>)
+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)]
index 8dc1c96..4980f8d 100644 (file)
@@ -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);
 }