mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-05-23 02:40:13 +02:00
wip
This commit is contained in:
parent
c4958b67de
commit
9d5daf868e
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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user