diff options
Diffstat (limited to 'exercises/20_threads')
| -rw-r--r-- | exercises/20_threads/README.md | 9 | ||||
| -rw-r--r-- | exercises/20_threads/threads1.rs | 40 | ||||
| -rw-r--r-- | exercises/20_threads/threads2.rs | 39 | ||||
| -rw-r--r-- | exercises/20_threads/threads3.rs | 67 |
4 files changed, 155 insertions, 0 deletions
diff --git a/exercises/20_threads/README.md b/exercises/20_threads/README.md new file mode 100644 index 0000000..dbe6664 --- /dev/null +++ b/exercises/20_threads/README.md @@ -0,0 +1,9 @@ +# Threads + +In most current operating systems, an executed program's code is run in a process, and the operating system manages multiple processes at once. +Within your program, you can also have independent parts that run simultaneously. The features that run these independent parts are called threads. + +## Further information + +- [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) diff --git a/exercises/20_threads/threads1.rs b/exercises/20_threads/threads1.rs new file mode 100644 index 0000000..80b6def --- /dev/null +++ b/exercises/20_threads/threads1.rs @@ -0,0 +1,40 @@ +// 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}; + +fn main() { + let mut handles = vec![]; + for i in 0..10 { + handles.push(thread::spawn(move || { + let start = Instant::now(); + thread::sleep(Duration::from_millis(250)); + println!("thread {} is complete", i); + start.elapsed().as_millis() + })); + } + + let mut results: Vec<u128> = vec![]; + for handle in handles { + // TODO: a struct is returned from thread::spawn, can you use it? + } + + if results.len() != 10 { + panic!("Oh no! All the spawned threads did not finish!"); + } + + println!(); + for (i, result) in results.into_iter().enumerate() { + println!("thread {} took {}ms", i, result); + } +} diff --git a/exercises/20_threads/threads2.rs b/exercises/20_threads/threads2.rs new file mode 100644 index 0000000..62dad80 --- /dev/null +++ b/exercises/20_threads/threads2.rs @@ -0,0 +1,39 @@ +// 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. + +// I AM NOT DONE + +use std::sync::Arc; +use std::thread; +use std::time::Duration; + +struct JobStatus { + jobs_completed: u32, +} + +fn main() { + let status = Arc::new(JobStatus { jobs_completed: 0 }); + let mut handles = vec![]; + 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; + }); + handles.push(handle); + } + 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 {}", ???); + } +} diff --git a/exercises/20_threads/threads3.rs b/exercises/20_threads/threads3.rs new file mode 100644 index 0000000..91006bb --- /dev/null +++ b/exercises/20_threads/threads3.rs @@ -0,0 +1,67 @@ +// 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; + +struct Queue { + length: u32, + first_half: Vec<u32>, + second_half: Vec<u32>, +} + +impl Queue { + fn new() -> Self { + Queue { + length: 10, + first_half: vec![1, 2, 3, 4, 5], + second_half: vec![6, 7, 8, 9, 10], + } + } +} + +fn send_tx(q: Queue, tx: mpsc::Sender<u32>) -> () { + let qc = Arc::new(q); + let qc1 = Arc::clone(&qc); + let qc2 = Arc::clone(&qc); + + thread::spawn(move || { + for val in &qc1.first_half { + println!("sending {:?}", val); + tx.send(*val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); + + thread::spawn(move || { + for val in &qc2.second_half { + println!("sending {:?}", val); + tx.send(*val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); +} + +#[test] +fn main() { + let (tx, rx) = mpsc::channel(); + let queue = Queue::new(); + let queue_length = queue.length; + + send_tx(queue, tx); + + let mut total_received: u32 = 0; + for received in rx { + println!("Got: {}", received); + total_received += 1; + } + + println!("total numbers received: {}", total_received); + assert_eq!(total_received, queue_length) +} |
