1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-05-22 18:30:33 +02:00
This commit is contained in:
Martin Geisler 2024-07-22 14:53:44 +02:00
parent c4958b67de
commit 9d5daf868e
10 changed files with 24 additions and 26 deletions

4
Cargo.lock generated
View File

@ -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"

View File

@ -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",

View File

@ -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)

View File

@ -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}}

View File

@ -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");
} }

View File

@ -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(())
} }
``` ```

View File

@ -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

View File

@ -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`:

View File

@ -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;
} }

View File

@ -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.