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