diff options
Diffstat (limited to 'exercises/20_threads')
| -rw-r--r-- | exercises/20_threads/README.md | 1 | ||||
| -rw-r--r-- | exercises/20_threads/threads1.rs | 31 | ||||
| -rw-r--r-- | exercises/20_threads/threads2.rs | 37 | ||||
| -rw-r--r-- | exercises/20_threads/threads3.rs | 71 |
4 files changed, 65 insertions, 75 deletions
diff --git a/exercises/20_threads/README.md b/exercises/20_threads/README.md index dbe6664..0b32fb1 100644 --- a/exercises/20_threads/README.md +++ b/exercises/20_threads/README.md @@ -7,3 +7,4 @@ Within your program, you can also have independent parts that run simultaneously - [Dining Philosophers example](https://doc.rust-lang.org/1.4.0/book/dining-philosophers.html) - [Using Threads to Run Code Simultaneously](https://doc.rust-lang.org/book/ch16-01-threads.html) +- [Using Message Passing to Transfer Data Between Threads](https://doc.rust-lang.org/book/ch16-02-message-passing.html) diff --git a/exercises/20_threads/threads1.rs b/exercises/20_threads/threads1.rs index 80b6def..01f9ff4 100644 --- a/exercises/20_threads/threads1.rs +++ b/exercises/20_threads/threads1.rs @@ -1,40 +1,37 @@ -// threads1.rs -// // This program spawns multiple threads that each run for at least 250ms, and // each thread returns how much time they took to complete. The program should // wait until all the spawned threads have finished and should collect their // return values into a vector. -// -// Execute `rustlings hint threads1` or use the `hint` watch subcommand for a -// hint. -// I AM NOT DONE - -use std::thread; -use std::time::{Duration, Instant}; +use std::{ + thread, + time::{Duration, Instant}, +}; fn main() { - let mut handles = vec![]; + let mut handles = Vec::new(); for i in 0..10 { - handles.push(thread::spawn(move || { + let handle = thread::spawn(move || { let start = Instant::now(); thread::sleep(Duration::from_millis(250)); - println!("thread {} is complete", i); + println!("Thread {i} done"); start.elapsed().as_millis() - })); + }); + handles.push(handle); } - let mut results: Vec<u128> = vec![]; + let mut results = Vec::new(); for handle in handles { - // TODO: a struct is returned from thread::spawn, can you use it? + // TODO: Collect the results of all threads into the `results` vector. + // Use the `JoinHandle` struct which is returned by `thread::spawn`. } if results.len() != 10 { - panic!("Oh no! All the spawned threads did not finish!"); + panic!("Oh no! Some thread isn't done yet!"); } println!(); for (i, result) in results.into_iter().enumerate() { - println!("thread {} took {}ms", i, result); + println!("Thread {i} took {result}ms"); } } diff --git a/exercises/20_threads/threads2.rs b/exercises/20_threads/threads2.rs index 62dad80..7020cb9 100644 --- a/exercises/20_threads/threads2.rs +++ b/exercises/20_threads/threads2.rs @@ -1,39 +1,34 @@ -// threads2.rs -// // 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 -// -// Execute `rustlings hint threads2` or use the `hint` watch subcommand for a -// hint. +// work. But this time, the spawned threads need to be in charge of updating a +// shared value: `JobStatus.jobs_done` -// I AM NOT 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() { - let status = Arc::new(JobStatus { jobs_completed: 0 }); - let mut handles = vec![]; + // TODO: `Arc` isn't enough if you want a **mutable** shared state. + let status = Arc::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)); - // 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. for handle in handles { handle.join().unwrap(); - // TODO: Print the value of the JobStatus.jobs_completed. Did you notice - // anything interesting in the output? Do you have to 'join' on all the - // handles? - println!("jobs completed {}", ???); } + + // TODO: Print the value of `JobStatus.jobs_done`. + println!("Jobs done: {}", todo!()); } diff --git a/exercises/20_threads/threads3.rs b/exercises/20_threads/threads3.rs index 91006bb..8aa7291 100644 --- a/exercises/20_threads/threads3.rs +++ b/exercises/20_threads/threads3.rs @@ -1,14 +1,4 @@ -// threads3.rs -// -// Execute `rustlings hint threads3` or use the `hint` watch subcommand for a -// hint. - -// I AM NOT DONE - -use std::sync::mpsc; -use std::sync::Arc; -use std::thread; -use std::time::Duration; +use std::{sync::mpsc, thread, time::Duration}; struct Queue { length: u32, @@ -18,7 +8,7 @@ struct Queue { impl Queue { fn new() -> Self { - Queue { + Self { length: 10, first_half: vec![1, 2, 3, 4, 5], second_half: vec![6, 7, 8, 9, 10], @@ -26,42 +16,49 @@ impl Queue { } } -fn send_tx(q: Queue, tx: mpsc::Sender<u32>) -> () { - let qc = Arc::new(q); - let qc1 = Arc::clone(&qc); - let qc2 = Arc::clone(&qc); - +fn send_tx(q: Queue, tx: mpsc::Sender<u32>) { + // TODO: We want to send `tx` to both threads. But currently, it is moved + // into the first thread. How could you solve this problem? thread::spawn(move || { - for val in &qc1.first_half { - println!("sending {:?}", val); - tx.send(*val).unwrap(); - thread::sleep(Duration::from_secs(1)); + for val in q.first_half { + println!("Sending {val:?}"); + tx.send(val).unwrap(); + thread::sleep(Duration::from_millis(250)); } }); thread::spawn(move || { - for val in &qc2.second_half { - println!("sending {:?}", val); - tx.send(*val).unwrap(); - thread::sleep(Duration::from_secs(1)); + for val in q.second_half { + println!("Sending {val:?}"); + tx.send(val).unwrap(); + thread::sleep(Duration::from_millis(250)); } }); } -#[test] fn main() { - let (tx, rx) = mpsc::channel(); - let queue = Queue::new(); - let queue_length = queue.length; + // You can optionally experiment here. +} - send_tx(queue, tx); +#[cfg(test)] +mod tests { + use super::*; - let mut total_received: u32 = 0; - for received in rx { - println!("Got: {}", received); - total_received += 1; - } + #[test] + fn threads3() { + let (tx, rx) = mpsc::channel(); + let queue = Queue::new(); + let queue_length = queue.length; - println!("total numbers received: {}", total_received); - assert_eq!(total_received, queue_length) + send_tx(queue, tx); + + let mut total_received: u32 = 0; + for received in rx { + println!("Got: {received}"); + total_received += 1; + } + + println!("Number of received values: {total_received}"); + assert_eq!(total_received, queue_length); + } } |
