Change story of exercise async1

- Remove confusing use of atomics. Use return values of async tasks
  instead, to ensure all tasks are awaited.
- Remove use of `println!()`, which uses a global lock and cannot be
  executed in parallel.
This commit is contained in:
Remo Senekowitsch 2026-04-25 15:07:13 +02:00
parent 229ca5acc9
commit 02a877c00c
No known key found for this signature in database
2 changed files with 54 additions and 78 deletions

View File

@ -1,15 +1,11 @@
// Tim has to complete a few chores today, before he's allowed to play soccer // Alice is an elementary school teacher who needs to calculate the mean test
// with his friends. His friends decide to help him. Working together, they // score for three classes she teaches. Instead of calculating them one after
// finish the chores earlier and have more time left to play soccer. // 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 boy is represented // Let's simulate this using asynchronous programming. Each person is
// as an asynchronous task, which can be executed concurrently (they can be // represented as an asynchronous task, which can be executed concurrently (i.e.
// working at the same time). // they can be doing the calculations at the same time).
use std::sync::atomic::{AtomicU8, Ordering};
// Used by "mom" to check that all chores are done before Tim plays soccer :-)
static CHORES_DONE: AtomicU8 = AtomicU8::new(0);
fn main() { fn main() {
// Async tasks need to be executed by a "runtime", which is not provided by // Async tasks need to be executed by a "runtime", which is not provided by
@ -18,38 +14,29 @@ fn main() {
.build() .build()
.unwrap(); .unwrap();
// TODO: Fix the compiler errors by making the spawned function async. let scores_class_a = &[83, 77, 92];
let task_tim = rt.spawn(tim()); let scores_class_b = &[84, 88, 96];
let task_carl = rt.spawn(carl()); let scores_class_c = &[71, 83, 76];
let task_nick = rt.spawn(nick());
// Block the runtime on a task that waits for all boys to finish the chores. // TODO: Fix the compiler errors by making the spawned function async.
// TODO: "await" all three tasks to fix the compiler errors. let alice = rt.spawn(calculate_mean_score(scores_class_a));
rt.block_on(async { let bob = rt.spawn(calculate_mean_score(scores_class_b));
task_tim; let catherine = rt.spawn(calculate_mean_score(scores_class_c));
task_carl;
task_nick; // 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!( assert_eq!(mean_score_a, 84);
CHORES_DONE.load(Ordering::SeqCst), assert_eq!(mean_score_b, 89);
3, assert_eq!(mean_score_c, 76);
"Did you (a)wait for all the boys to finish the chores?"
);
println!("Ready to play soccer!");
} }
fn tim() { fn calculate_mean_score(score_list: &[usize]) -> usize {
println!("Cleaning my room..."); let score_sum: usize = score_list.iter().sum();
CHORES_DONE.fetch_add(1, Ordering::SeqCst); score_sum / score_list.len()
}
fn carl() {
println!("Washing the dishes...");
CHORES_DONE.fetch_add(1, Ordering::SeqCst);
}
fn nick() {
println!("Mowing the lawn...");
CHORES_DONE.fetch_add(1, Ordering::SeqCst);
} }

View File

@ -1,15 +1,11 @@
// Tim has to complete a few chores today, before he's allowed to play soccer // Alice is an elementary school teacher who needs to calculate the mean test
// with his friends. His friends decide to help him. Working together, they // score for three classes she teaches. Instead of calculating them one after
// finish the chores earlier and have more time left to play soccer. // 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 boy is represented // Let's simulate this using asynchronous programming. Each person is
// as an asynchronous task, which can be executed concurrently (they can be // represented as an asynchronous task, which can be executed concurrently (i.e.
// working at the same time). // they can be doing the calculations at the same time).
use std::sync::atomic::{AtomicU8, Ordering};
// Used by "mom" to check that all chores are done before Tim plays soccer :-)
static CHORES_DONE: AtomicU8 = AtomicU8::new(0);
fn main() { fn main() {
// Async tasks need to be executed by a "runtime", which is not provided by // Async tasks need to be executed by a "runtime", which is not provided by
@ -18,36 +14,29 @@ fn main() {
.build() .build()
.unwrap(); .unwrap();
let task_tim = rt.spawn(tim()); let scores_class_a = &[83, 77, 92];
let task_carl = rt.spawn(carl()); let scores_class_b = &[84, 88, 96];
let task_nick = rt.spawn(nick()); let scores_class_c = &[71, 83, 76];
// Block the runtime on a task that waits for all boys to finish the chores. let alice = rt.spawn(calculate_mean_score(scores_class_a));
rt.block_on(async { let bob = rt.spawn(calculate_mean_score(scores_class_b));
task_tim.await.unwrap(); let catherine = rt.spawn(calculate_mean_score(scores_class_c));
task_carl.await.unwrap();
task_nick.await.unwrap(); // 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!( assert_eq!(mean_score_a, 84);
CHORES_DONE.load(Ordering::SeqCst), assert_eq!(mean_score_b, 89);
3, assert_eq!(mean_score_c, 76);
"Did you (a)wait for all the boys to finish the chores?"
);
println!("Ready to play soccer!");
} }
async fn tim() { async fn calculate_mean_score(score_list: &[usize]) -> usize {
println!("Cleaning my room..."); let score_sum: usize = score_list.iter().sum();
CHORES_DONE.fetch_add(1, Ordering::SeqCst); score_sum / score_list.len()
}
async fn carl() {
println!("Washing the dishes...");
CHORES_DONE.fetch_add(1, Ordering::SeqCst);
}
async fn nick() {
println!("Mowing the lawn...");
CHORES_DONE.fetch_add(1, Ordering::SeqCst);
} }