From dfa2b44f718906dfac54816bb582880066c3dff0 Mon Sep 17 00:00:00 2001 From: mo8it Date: Mon, 1 Jul 2024 11:11:11 +0200 Subject: [PATCH] threads2 solution --- exercises/20_threads/threads2.rs | 27 ++++++++++---------- rustlings-macros/info.toml | 10 ++++---- solutions/20_threads/threads2.rs | 42 +++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 20 deletions(-) diff --git a/exercises/20_threads/threads2.rs b/exercises/20_threads/threads2.rs index 2bdeba94..7020cb9c 100644 --- a/exercises/20_threads/threads2.rs +++ b/exercises/20_threads/threads2.rs @@ -1,35 +1,34 @@ // Building on the last exercise, we want all of the threads to complete their -// work but this time the spawned threads need to be in charge of updating a -// shared value: JobStatus.jobs_completed +// work. But this time, the spawned threads need to be in charge of updating a +// shared value: `JobStatus.jobs_done` -use std::sync::Arc; -use std::thread; -use std::time::Duration; +use std::{sync::Arc, thread, time::Duration}; struct JobStatus { - jobs_completed: u32, + jobs_done: u32, } fn main() { - // TODO: `Arc` isn't enough if you want a **mutable** shared state - let status = Arc::new(JobStatus { jobs_completed: 0 }); + // TODO: `Arc` isn't enough if you want a **mutable** shared state. + let status = Arc::new(JobStatus { jobs_done: 0 }); - let mut handles = vec![]; + let mut handles = Vec::new(); for _ in 0..10 { let status_shared = Arc::clone(&status); let handle = thread::spawn(move || { thread::sleep(Duration::from_millis(250)); - // TODO: You must take an action before you update a shared value - status_shared.jobs_completed += 1; + + // TODO: You must take an action before you update a shared value. + status_shared.jobs_done += 1; }); handles.push(handle); } - // Waiting for all jobs to complete + // Waiting for all jobs to complete. for handle in handles { handle.join().unwrap(); } - // TODO: Print the value of `JobStatus.jobs_completed` - println!("Jobs completed: {}", ???); + // TODO: Print the value of `JobStatus.jobs_done`. + println!("Jobs done: {}", todo!()); } diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index 37afa178..ab8c1215 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -1051,19 +1051,19 @@ dir = "20_threads" test = false hint = """ `Arc` is an Atomic Reference Counted pointer that allows safe, shared access -to **immutable** data. But we want to *change* the number of `jobs_completed` -so we'll need to also use another type that will only allow one thread to -mutate the data at a time. Take a look at this section of the book: +to **immutable** data. But we want to *change* the number of `jobs_done` so +we'll need to also use another type that will only allow one thread to mutate +the data at a time. Take a look at this section of the book: https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct Keep reading if you'd like more hints :) Do you now have an `Arc>` at the beginning of `main`? Like: ``` -let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 })); +let status = Arc::new(Mutex::new(JobStatus { jobs_done: 0 })); ``` -Similar to the code in the following example in the book: +Similar to the code in the following example in The Book: https://doc.rust-lang.org/book/ch16-03-shared-state.html#sharing-a-mutext-between-multiple-threads""" [[exercises]] diff --git a/solutions/20_threads/threads2.rs b/solutions/20_threads/threads2.rs index 4e181989..bc268d63 100644 --- a/solutions/20_threads/threads2.rs +++ b/solutions/20_threads/threads2.rs @@ -1 +1,41 @@ -// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 +// Building on the last exercise, we want all of the threads to complete their +// work. But this time, the spawned threads need to be in charge of updating a +// shared value: `JobStatus.jobs_done` + +use std::{ + sync::{Arc, Mutex}, + thread, + time::Duration, +}; + +struct JobStatus { + jobs_done: u32, +} + +fn main() { + // `Arc` isn't enough if you want a **mutable** shared state. + // We need to wrap the value with a `Mutex`. + let status = Arc::new(Mutex::new(JobStatus { jobs_done: 0 })); + // ^^^^^^^^^^^ ^ + + let mut handles = Vec::new(); + for _ in 0..10 { + let status_shared = Arc::clone(&status); + let handle = thread::spawn(move || { + thread::sleep(Duration::from_millis(250)); + + // Lock before you update a shared value. + status_shared.lock().unwrap().jobs_done += 1; + // ^^^^^^^^^^^^^^^^ + }); + handles.push(handle); + } + + // Waiting for all jobs to complete. + for handle in handles { + handle.join().unwrap(); + } + + println!("Jobs done: {}", status.lock().unwrap().jobs_done); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +}