Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ bin = [
{ name = "try_from_into_sol", path = "../solutions/23_conversions/try_from_into.rs" },
{ name = "as_ref_mut", path = "../exercises/23_conversions/as_ref_mut.rs" },
{ name = "as_ref_mut_sol", path = "../solutions/23_conversions/as_ref_mut.rs" },
{ name = "async1", path = "../exercises/24_async/async1.rs" },
{ name = "async1_sol", path = "../solutions/24_async/async1.rs" },
]

[package]
Expand All @@ -196,6 +198,9 @@ edition = "2024"
# Don't publish the exercises on crates.io!
publish = false

[dependencies]
tokio = { version = "1", features = ["rt"] }

[profile.release]
panic = "abort"

Expand Down
13 changes: 13 additions & 0 deletions exercises/24_async/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Async

Asynchronous programming is a model where tasks are delegated to a runtime that executes them concurrently.
It is particularly efficient for applications where many independent IO-operations are performed, e.g. web servers.

Rust provides the necessary primitives to do asynchronous programming in the language.
However, Rust's standard library does not include a runtime.
For these exercises, we will use the mainstream runtime called `tokio`.

## Further information

- [Fundamentals of Asynchronous Programming](https://doc.rust-lang.org/book/ch17-00-async-await.html)
- [Tokio documentation](https://docs.rs/tokio/latest/tokio/)
42 changes: 42 additions & 0 deletions exercises/24_async/async1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Alice is an elementary school teacher who needs to calculate the mean test
// score for three classes she teaches. Instead of calculating them one after
// the other, she decides to ask her friends Bob and Catherine for help. Working
// together, they can finish the job much faster.
//
// Let's simulate this using asynchronous programming. Each person is
// represented as an asynchronous task, which can be executed concurrently (i.e.
// they can be doing the calculations at the same time).

fn main() {
// Async tasks need to be executed by a "runtime", which is not provided by
// Rust's standard library. Here, we use the mainstream runtime `tokio`.
let rt = tokio::runtime::Builder::new_current_thread()
.build()
.unwrap();

let scores_class_a = &[83, 77, 92];
let scores_class_b = &[84, 88, 96];
let scores_class_c = &[71, 83, 76];

// TODO: Fix the compiler errors by making the spawned function async.
let alice = rt.spawn(calculate_mean_score(scores_class_a));
let bob = rt.spawn(calculate_mean_score(scores_class_b));
let catherine = rt.spawn(calculate_mean_score(scores_class_c));

// Block the runtime on a task that awaits all three calculations.
let [mean_score_a, mean_score_b, mean_score_c]: [usize; _] = rt.block_on(async {
[
// TODO: "await" all three tasks to fix the compiler error.
alice, bob, catherine,
]
});

assert_eq!(mean_score_a, 84);
assert_eq!(mean_score_b, 89);
assert_eq!(mean_score_c, 76);
}

fn calculate_mean_score(score_list: &[usize]) -> usize {
let score_sum: usize = score_list.iter().sum();
score_sum / score_list.len()
}
14 changes: 14 additions & 0 deletions rustlings-macros/info.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1199,3 +1199,17 @@ name = "as_ref_mut"
dir = "23_conversions"
hint = """
Add `AsRef<str>` or `AsMut<u32>` as a trait bound to the functions."""

# ASYNC

[[exercises]]
name = "async1"
dir = "24_async"
test = false
hint = """
Asynchronous runtimes like tokio can only spawn tasks that are defined as async
functions, not regular ones. Add the "async" keyword before the "fn" keyword of
the functions "tim", "carl" and "nick".

An async task can wait for another one to complete by "awaiting" it. Add
".await" after the three "task_name" variables in the "block_on" call."""
42 changes: 42 additions & 0 deletions solutions/24_async/async1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Alice is an elementary school teacher who needs to calculate the mean test
// score for three classes she teaches. Instead of calculating them one after
// the other, she decides to ask her friends Bob and Catherine for help. Working
// together, they can finish the job much faster.
//
// Let's simulate this using asynchronous programming. Each person is
// represented as an asynchronous task, which can be executed concurrently (i.e.
// they can be doing the calculations at the same time).

fn main() {
// Async tasks need to be executed by a "runtime", which is not provided by
// Rust's standard library. Here, we use the mainstream runtime `tokio`.
let rt = tokio::runtime::Builder::new_current_thread()
.build()
.unwrap();

let scores_class_a = &[83, 77, 92];
let scores_class_b = &[84, 88, 96];
let scores_class_c = &[71, 83, 76];

let alice = rt.spawn(calculate_mean_score(scores_class_a));
let bob = rt.spawn(calculate_mean_score(scores_class_b));
let catherine = rt.spawn(calculate_mean_score(scores_class_c));

// Block the runtime on a task that awaits all three calculations.
let [mean_score_a, mean_score_b, mean_score_c]: [usize; _] = rt.block_on(async {
[
alice.await.unwrap(),
bob.await.unwrap(),
catherine.await.unwrap(),
]
});

assert_eq!(mean_score_a, 84);
assert_eq!(mean_score_b, 89);
assert_eq!(mean_score_c, 76);
}

async fn calculate_mean_score(score_list: &[usize]) -> usize {
let score_sum: usize = score_list.iter().sum();
score_sum / score_list.len()
}