X-Git-Url: https://git.ralfj.de/rust-101.git/blobdiff_plain/188b1ec1b8528e2326791feccc8077e15bd60182..57fd78e47f3f9d935f62a5dc05e8676ae035ad3d:/workspace/src/part15.rs?ds=sidebyside diff --git a/workspace/src/part15.rs b/workspace/src/part15.rs index d006b23..148f648 100644 --- a/workspace/src/part15.rs +++ b/workspace/src/part15.rs @@ -1,8 +1,9 @@ -// Rust-101, Part 15: Mutex, Interior Mutability (cont.), Sync -// =========================================================== +// Rust-101, Part 15: Mutex, Interior Mutability (cont.), RwLock, Sync +// =================================================================== use std::sync::{Arc, Mutex}; use std::thread; +use std::time::Duration; // The derived `Clone` implementation will clone the `Arc`, so all clones will actually talk about the same counter. @@ -15,8 +16,9 @@ impl ConcurrentCounter { unimplemented!() } + // The core operation is, of course, `increment`. pub fn increment(&self, by: usize) { - // `lock` on a mutex returns a *guard*, giving access to the data contained in the mutex. + // `lock` on a mutex returns a guard, very much like `RefCell`. The guard gives access to the data contained in the mutex. let mut counter = self.0.lock().unwrap(); *counter = *counter + by; } @@ -35,7 +37,7 @@ pub fn main() { let counter1 = counter.clone(); let handle1 = thread::spawn(move || { for _ in 0..10 { - thread::sleep_ms(15); + thread::sleep(Duration::from_millis(15)); counter1.increment(2); } }); @@ -44,14 +46,14 @@ pub fn main() { let counter2 = counter.clone(); let handle2 = thread::spawn(move || { for _ in 0..10 { - thread::sleep_ms(20); + thread::sleep(Duration::from_millis(20)); counter2.increment(3); } }); // Now we watch the threads working on the counter. for _ in 0..50 { - thread::sleep_ms(5); + thread::sleep(Duration::from_millis(5)); println!("Current value: {}", counter.get()); } @@ -61,16 +63,13 @@ pub fn main() { println!("Final value: {}", counter.get()); } -// **Exercise 14.1**: Besides `Mutex`, there's also [`RwLock`](http://doc.rust-lang.org/stable/std/sync/struct.RwLock.html), which -// provides two ways of locking: One that grants only read-only access, to any number of concurrent readers, and another one -// for exclusive write access. (Notice that this is the same pattern we already saw with shared vs. mutable borrows.) Change -// the code above to use `RwLock`, such that multiple calls to `get` can be executed at the same time. -// -// **Exercise 14.2**: Add an operation `compare_and_inc(&self, test: usize, by: usize)` that increments the counter by +// **Exercise 15.1**: Add an operation `compare_and_inc(&self, test: usize, by: usize)` that increments the counter by // `by` *only if* the current value is `test`. +// +// **Exercise 15.2**: Rather than panicking in case the lock is poisoned, we can use `into_inner` on the error to recover +// the data inside the lock. Change the code above to do that. Try using `unwrap_or_else` for this job. -// FIXME TODO some old outdated explanation FIXME TODO - +// **Exercise 15.3**: Change the code above to use `RwLock`, such that multiple calls to `get` can be executed at the same time.