diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/basic.rs | 2 | ||||
| -rw-r--r-- | examples/dining_philosophers.rs | 14 | ||||
| -rw-r--r-- | examples/dining_philosophers_retry.rs | 75 | ||||
| -rw-r--r-- | examples/double_mutex.rs | 10 | ||||
| -rw-r--r-- | examples/fibonacci.rs | 29 | ||||
| -rw-r--r-- | examples/list.rs | 8 |
6 files changed, 123 insertions, 15 deletions
diff --git a/examples/basic.rs b/examples/basic.rs index 1d611d3..b9c5641 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -23,5 +23,5 @@ fn main() { let key = ThreadKey::get().unwrap(); let data = DATA.lock(key); - println!("{}", *data); + println!("{data}"); } diff --git a/examples/dining_philosophers.rs b/examples/dining_philosophers.rs index 35aa330..dc4dd51 100644 --- a/examples/dining_philosophers.rs +++ b/examples/dining_philosophers.rs @@ -1,6 +1,6 @@ use std::{thread, time::Duration}; -use happylock::{LockCollection, Mutex, ThreadKey}; +use happylock::{collection, Mutex, ThreadKey}; static PHILOSOPHERS: [Philosopher; 5] = [ Philosopher { @@ -50,8 +50,8 @@ impl Philosopher { thread::sleep(Duration::from_secs(1)); // safety: no philosopher asks for the same fork twice - let forks = - unsafe { LockCollection::new_unchecked([&FORKS[self.left], &FORKS[self.right]]) }; + let forks = [&FORKS[self.left], &FORKS[self.right]]; + let forks = unsafe { collection::RefLockCollection::new_unchecked(&forks) }; let forks = forks.lock(key); println!("{} is eating...", self.name); thread::sleep(Duration::from_secs(1)); @@ -61,9 +61,13 @@ impl Philosopher { } fn main() { - let handles = PHILOSOPHERS + let handles: Vec<_> = PHILOSOPHERS .iter() - .map(|philosopher| thread::spawn(move || philosopher.cycle())); + .map(|philosopher| thread::spawn(move || philosopher.cycle())) + // The `collect` is absolutely necessary, because we're using lazy + // iterators. If `collect` isn't used, then the thread won't spawn + // until we try to join on it. + .collect(); for handle in handles { _ = handle.join(); diff --git a/examples/dining_philosophers_retry.rs b/examples/dining_philosophers_retry.rs new file mode 100644 index 0000000..4302bc7 --- /dev/null +++ b/examples/dining_philosophers_retry.rs @@ -0,0 +1,75 @@ +use std::{thread, time::Duration}; + +use happylock::{collection, Mutex, ThreadKey}; + +static PHILOSOPHERS: [Philosopher; 5] = [ + Philosopher { + name: "Socrates", + left: 0, + right: 1, + }, + Philosopher { + name: "John Rawls", + left: 1, + right: 2, + }, + Philosopher { + name: "Jeremy Bentham", + left: 2, + right: 3, + }, + Philosopher { + name: "John Stuart Mill", + left: 3, + right: 4, + }, + Philosopher { + name: "Judith Butler", + left: 4, + right: 0, + }, +]; + +static FORKS: [Mutex<()>; 5] = [ + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), +]; + +struct Philosopher { + name: &'static str, + left: usize, + right: usize, +} + +impl Philosopher { + fn cycle(&self) { + let key = ThreadKey::get().unwrap(); + thread::sleep(Duration::from_secs(1)); + + // safety: no philosopher asks for the same fork twice + let forks = [&FORKS[self.left], &FORKS[self.right]]; + let forks = unsafe { collection::RetryingLockCollection::new_unchecked(&forks) }; + let forks = forks.lock(key); + println!("{} is eating...", self.name); + thread::sleep(Duration::from_secs(1)); + println!("{} is done eating", self.name); + drop(forks); + } +} + +fn main() { + let handles: Vec<_> = PHILOSOPHERS + .iter() + .map(|philosopher| thread::spawn(move || philosopher.cycle())) + // The `collect` is absolutely necessary, because we're using lazy + // iterators. If `collect` isn't used, then the thread won't spawn + // until we try to join on it. + .collect(); + + for handle in handles { + _ = handle.join(); + } +} diff --git a/examples/double_mutex.rs b/examples/double_mutex.rs index 621f81e..ea61f0d 100644 --- a/examples/double_mutex.rs +++ b/examples/double_mutex.rs @@ -1,6 +1,6 @@ use std::thread; -use happylock::{LockCollection, Mutex, ThreadKey}; +use happylock::{collection::RefLockCollection, Mutex, ThreadKey}; const N: usize = 10; @@ -11,7 +11,7 @@ fn main() { for _ in 0..N { let th = thread::spawn(move || { let key = ThreadKey::get().unwrap(); - let lock = LockCollection::new_ref(&DATA); + let lock = RefLockCollection::new(&DATA); let mut guard = lock.lock(key); *guard.1 = (100 - *guard.0).to_string(); *guard.0 += 1; @@ -24,8 +24,8 @@ fn main() { } let key = ThreadKey::get().unwrap(); - let data = LockCollection::new_ref(&DATA); + let data = RefLockCollection::new(&DATA); let data = data.lock(key); - println!("{}", *data.0); - println!("{}", *data.1); + println!("{}", data.0); + println!("{}", data.1); } diff --git a/examples/fibonacci.rs b/examples/fibonacci.rs new file mode 100644 index 0000000..d43b01c --- /dev/null +++ b/examples/fibonacci.rs @@ -0,0 +1,29 @@ +use happylock::{LockCollection, Mutex, ThreadKey}; +use std::thread; + +const N: usize = 36; + +static DATA: [Mutex<i32>; 2] = [Mutex::new(0), Mutex::new(1)]; + +fn main() { + for _ in 0..N { + thread::spawn(move || { + let key = ThreadKey::get().unwrap(); + + // a reference to a type that implements `OwnedLockable` will never + // contain duplicates, so no duplicate checking is needed. + let collection = LockCollection::new_ref(&DATA); + let mut guard = collection.lock(key); + + let x = *guard[1]; + *guard[1] += *guard[0]; + *guard[0] = x; + }); + } + + let key = ThreadKey::get().unwrap(); + let data = LockCollection::new_ref(&DATA); + let data = data.lock(key); + println!("{}", data[0]); + println!("{}", data[1]); +} diff --git a/examples/list.rs b/examples/list.rs index 3b03f2d..a649eeb 100644 --- a/examples/list.rs +++ b/examples/list.rs @@ -1,6 +1,6 @@ use std::thread; -use happylock::{LockCollection, Mutex, ThreadKey}; +use happylock::{collection::RefLockCollection, Mutex, ThreadKey}; const N: usize = 10; @@ -37,7 +37,7 @@ fn main() { data.push(&DATA[rand % 6]); } - let Some(lock) = LockCollection::try_new(data) else { + let Some(lock) = RefLockCollection::try_new(&data) else { continue; }; let mut guard = lock.lock(&mut key); @@ -56,9 +56,9 @@ fn main() { } let key = ThreadKey::get().unwrap(); - let data = LockCollection::new_ref(&DATA); + let data = RefLockCollection::new(&DATA); let data = data.lock(key); for val in &*data { - println!("{}", **val); + println!("{val}"); } } |
