You've already forked comprehensive-rust
							
							
				mirror of
				https://github.com/google/comprehensive-rust.git
				synced 2025-10-31 08:37:45 +02:00 
			
		
		
		
	wip
This commit is contained in:
		
							
								
								
									
										4
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -373,6 +373,10 @@ version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" | ||||
|  | ||||
| [[package]] | ||||
| name = "concurrency" | ||||
| version = "0.1.0" | ||||
|  | ||||
| [[package]] | ||||
| name = "control-flow-basics" | ||||
| version = "0.1.0" | ||||
|   | ||||
| @@ -9,6 +9,7 @@ members = [ | ||||
|   "src/borrowing", | ||||
|   "src/control-flow-basics", | ||||
|   "src/error-handling", | ||||
|   "src/concurrency", | ||||
|   "src/concurrency/sync-exercises", | ||||
|   "src/concurrency/async-exercises", | ||||
|   "src/concurrency/async-exercises/chat-async", | ||||
|   | ||||
| @@ -387,7 +387,7 @@ | ||||
|   - [Futures](concurrency/async/futures.md) | ||||
|   - [Runtimes](concurrency/async/runtimes.md) | ||||
|     - [Tokio](concurrency/async/runtimes/tokio.md) | ||||
|   - [Tasks](concurrency/async/tasks.md) | ||||
|     <!-- - [Tasks](concurrency/async/tasks.md) --> | ||||
| - [Channels and Control Flow](concurrency/async-control-flow.md) | ||||
|   - [Async Channels](concurrency/async-control-flow/channels.md) | ||||
|   - [Join](concurrency/async-control-flow/join.md) | ||||
|   | ||||
| @@ -4,7 +4,7 @@ minutes: 8 | ||||
|  | ||||
| # Async Channels | ||||
|  | ||||
| Several crates have support for asynchronous channels. For instance `tokio`: | ||||
| Asynchronous channels are very similar to synchronous channels: | ||||
|  | ||||
| ```rust,editable,compile_fail | ||||
| {{#include channels.rs}} | ||||
|   | ||||
| @@ -2,12 +2,10 @@ use tokio::sync::mpsc; | ||||
|  | ||||
| async fn ping_handler(mut input: mpsc::Receiver<()>) { | ||||
|     let mut count = 0; | ||||
|  | ||||
|     while let Some(_) = input.recv().await { | ||||
|         count += 1; | ||||
|         println!("Received {count} pings so far."); | ||||
|     } | ||||
|  | ||||
|     println!("ping_handler complete"); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -29,13 +29,13 @@ You are going to need the following functions from `tokio` and | ||||
| [`tokio_websockets`][2]. Spend a few minutes to familiarize yourself with the | ||||
| API. | ||||
|  | ||||
| - [StreamExt::next()][3] implemented by `WebSocketStream`: for asynchronously | ||||
| - [`StreamExt::next()`][3] implemented by `WebSocketStream`: for asynchronously | ||||
|   reading messages from a Websocket Stream. | ||||
| - [SinkExt::send()][4] implemented by `WebSocketStream`: for asynchronously | ||||
| - [`SinkExt::send()`][4] implemented by `WebSocketStream`: for asynchronously | ||||
|   sending messages on a Websocket Stream. | ||||
| - [Lines::next_line()][5]: for asynchronously reading user messages from the | ||||
| - [`Lines::next_line()`][5]: for asynchronously reading user messages from the | ||||
|   standard input. | ||||
| - [Sender::subscribe()][6]: for subscribing to a broadcast channel. | ||||
| - [`Sender::subscribe()`][6]: for subscribing to a broadcast channel. | ||||
|  | ||||
| ## Two binaries | ||||
|  | ||||
| @@ -58,9 +58,8 @@ _src/bin/server.rs_: | ||||
| {{#include chat-async/src/bin/server.rs:setup}} | ||||
|  | ||||
| {{#include chat-async/src/bin/server.rs:handle_connection}} | ||||
|  | ||||
|     // TODO: For a hint, see the description of the task below. | ||||
|  | ||||
|     Ok(()) | ||||
| {{#include chat-async/src/bin/server.rs:main}} | ||||
| ``` | ||||
|  | ||||
| @@ -72,7 +71,7 @@ _src/bin/client.rs_: | ||||
| {{#include chat-async/src/bin/client.rs:setup}} | ||||
|  | ||||
|     // TODO: For a hint, see the description of the task below. | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
| ``` | ||||
|  | ||||
|   | ||||
| @@ -44,13 +44,11 @@ impl Philosopher { | ||||
|         // Keep trying until we have both forks | ||||
|         // ANCHOR_END: Philosopher-eat | ||||
|         let (_left_fork, _right_fork) = loop { | ||||
|             tokio::task::yield_now().await; | ||||
|             // Pick up forks... | ||||
|             match (self.left_fork.try_lock(), self.right_fork.try_lock()) { | ||||
|                 (Ok(left_fork), Ok(right_fork)) => (left_fork, right_fork), | ||||
|                 (Ok(left_fork), Ok(right_fork)) => break (left_fork, right_fork), | ||||
|                 (_, _) => continue, | ||||
|             }; | ||||
|             break (left_fork, right_fork); | ||||
|         }; | ||||
|  | ||||
|         // ANCHOR: Philosopher-eat-body | ||||
|   | ||||
| @@ -4,9 +4,9 @@ minutes: 5 | ||||
|  | ||||
| # Async Traits | ||||
|  | ||||
| Async methods in traits are were stabilized in the 1.75 release. This required | ||||
| support for using return-position `impl Trait` in traits, as the desugaring for | ||||
| `async fn` includes `-> impl Future<Output = ...>`. | ||||
| Async methods in traits are were stabilized in the 1.75 release (December 2023). | ||||
| This required support for using return-position `impl Trait` in traits, as the | ||||
| desugaring for `async fn` includes `-> impl Future<Output = ...>`. | ||||
|  | ||||
| However, even with the native support, there are some pitfalls around | ||||
| `async fn`: | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| use async_trait::async_trait; | ||||
| use std::time::Instant; | ||||
| use tokio::time::{sleep, Duration}; | ||||
|  | ||||
| #[async_trait] | ||||
| @@ -18,14 +17,11 @@ impl Sleeper for FixedSleeper { | ||||
|     } | ||||
| } | ||||
|  | ||||
| async fn run_all_sleepers_multiple_times( | ||||
|     sleepers: Vec<Box<dyn Sleeper>>, | ||||
|     n_times: usize, | ||||
| ) { | ||||
|     for _ in 0..n_times { | ||||
| async fn run_all_sleepers_multiple_times(sleepers: Vec<Box<dyn Sleeper>>) { | ||||
|     for _ in 0..5 { | ||||
|         println!("Running all sleepers..."); | ||||
|         for sleeper in &sleepers { | ||||
|             let start = Instant::now(); | ||||
|             let start = std::time::Instant::now(); | ||||
|             sleeper.sleep().await; | ||||
|             println!("Slept for {} ms", start.elapsed().as_millis()); | ||||
|         } | ||||
| @@ -38,5 +34,5 @@ async fn main() { | ||||
|         Box::new(FixedSleeper { sleep_ms: 50 }), | ||||
|         Box::new(FixedSleeper { sleep_ms: 100 }), | ||||
|     ]; | ||||
|     run_all_sleepers_multiple_times(sleepers, 5).await; | ||||
|     run_all_sleepers_multiple_times(sleepers).await; | ||||
| } | ||||
|   | ||||
| @@ -5,9 +5,11 @@ minutes: 20 | ||||
| # `Pin` | ||||
|  | ||||
| Async blocks and functions return types implementing the `Future` trait. The | ||||
| type returned is the result of a compiler transformation which turns local | ||||
| type returned is the result of a [compiler transformation] which turns local | ||||
| variables into data stored inside the future. | ||||
|  | ||||
| [compiler transformation]: https://tokio.rs/tokio/tutorial/async | ||||
|  | ||||
| Some of those variables can hold pointers to other local variables. Because of | ||||
| that, the future should never be moved to a different memory location, as it | ||||
| would invalidate those pointers. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user