diff options
Diffstat (limited to 'src/collection')
| -rw-r--r-- | src/collection/boxed.rs | 93 | ||||
| -rw-r--r-- | src/collection/owned.rs | 4 | ||||
| -rw-r--r-- | src/collection/ref.rs | 26 | ||||
| -rw-r--r-- | src/collection/utils.rs | 2 |
4 files changed, 109 insertions, 16 deletions
diff --git a/src/collection/boxed.rs b/src/collection/boxed.rs index 72489bf..0597e90 100644 --- a/src/collection/boxed.rs +++ b/src/collection/boxed.rs @@ -628,6 +628,69 @@ mod tests { use crate::{Mutex, RwLock, ThreadKey}; #[test] + fn from_iterator() { + let key = ThreadKey::get().unwrap(); + let collection: BoxedLockCollection<Vec<Mutex<&str>>> = + [Mutex::new("foo"), Mutex::new("bar"), Mutex::new("baz")] + .into_iter() + .collect(); + let guard = collection.lock(key); + // TODO impl PartialEq<T> for MutexRef<T> + assert_eq!(*guard[0], "foo"); + assert_eq!(*guard[1], "bar"); + assert_eq!(*guard[2], "baz"); + } + + #[test] + fn from() { + let key = ThreadKey::get().unwrap(); + let collection = + BoxedLockCollection::from([Mutex::new("foo"), Mutex::new("bar"), Mutex::new("baz")]); + let guard = collection.lock(key); + // TODO impl PartialEq<T> for MutexRef<T> + assert_eq!(*guard[0], "foo"); + assert_eq!(*guard[1], "bar"); + assert_eq!(*guard[2], "baz"); + } + + #[test] + fn into_owned_iterator() { + let collection = BoxedLockCollection::new([Mutex::new(0), Mutex::new(1), Mutex::new(2)]); + for (i, mutex) in collection.into_iter().enumerate() { + assert_eq!(mutex.into_inner(), i); + } + } + + #[test] + fn into_ref_iterator() { + let mut key = ThreadKey::get().unwrap(); + let collection = BoxedLockCollection::new([Mutex::new(0), Mutex::new(1), Mutex::new(2)]); + for (i, mutex) in (&collection).into_iter().enumerate() { + assert_eq!(*mutex.lock(&mut key), i); + } + } + + #[test] + fn ref_iterator() { + let mut key = ThreadKey::get().unwrap(); + let collection = BoxedLockCollection::new([Mutex::new(0), Mutex::new(1), Mutex::new(2)]); + for (i, mutex) in collection.iter().enumerate() { + assert_eq!(*mutex.lock(&mut key), i); + } + } + + #[test] + #[allow(clippy::float_cmp)] + fn uses_correct_default() { + let collection = + BoxedLockCollection::<(Mutex<f64>, Mutex<Option<i32>>, Mutex<usize>)>::default(); + let tuple = collection.into_inner(); + assert_eq!(tuple.0, 0.0); + assert!(tuple.1.is_none()); + assert_eq!(tuple.2, 0) + } + + #[test] fn non_duplicates_allowed() { let mutex1 = Mutex::new(0); let mutex2 = Mutex::new(1); @@ -733,6 +796,36 @@ mod tests { } #[test] + fn unlock_collection_works() { + let key = ThreadKey::get().unwrap(); + let mutex1 = Mutex::new("foo"); + let mutex2 = Mutex::new("bar"); + let collection = BoxedLockCollection::try_new((&mutex1, &mutex2)).unwrap(); + let guard = collection.lock(key); + let key = BoxedLockCollection::<(&Mutex<_>, &Mutex<_>)>::unlock(guard); + + assert!(mutex1.try_lock(key).is_ok()) + } + + #[test] + fn read_unlock_collection_works() { + let key = ThreadKey::get().unwrap(); + let lock1 = RwLock::new("foo"); + let lock2 = RwLock::new("bar"); + let collection = BoxedLockCollection::try_new((&lock1, &lock2)).unwrap(); + let guard = collection.read(key); + let key = BoxedLockCollection::<(&RwLock<_>, &RwLock<_>)>::unlock_read(guard); + + assert!(lock1.try_write(key).is_ok()) + } + + #[test] + fn into_inner_works() { + let collection = BoxedLockCollection::new((Mutex::new("Hello"), Mutex::new(47))); + assert_eq!(collection.into_inner(), ("Hello", 47)) + } + + #[test] fn works_in_collection() { let key = ThreadKey::get().unwrap(); let mutex1 = Mutex::new(0); diff --git a/src/collection/owned.rs b/src/collection/owned.rs index 4a0d1ef..c345b43 100644 --- a/src/collection/owned.rs +++ b/src/collection/owned.rs @@ -197,7 +197,7 @@ impl<L: OwnedLockable> OwnedLockCollection<L> { /// *guard.0 += 1; /// *guard.1 = "1"; /// ``` - pub fn lock<'g, 'key, Key: Keyable + 'key>( + pub fn lock<'g, 'key: 'g, Key: Keyable + 'key>( &'g self, key: Key, ) -> LockGuard<'key, L::Guard<'g>, Key> { @@ -315,7 +315,7 @@ impl<L: Sharable> OwnedLockCollection<L> { /// assert_eq!(*guard.0, 0); /// assert_eq!(*guard.1, ""); /// ``` - pub fn read<'g, 'key, Key: Keyable + 'key>( + pub fn read<'g, 'key: 'g, Key: Keyable + 'key>( &'g self, key: Key, ) -> LockGuard<'key, L::ReadGuard<'g>, Key> { diff --git a/src/collection/ref.rs b/src/collection/ref.rs index 37973f6..c86f298 100644 --- a/src/collection/ref.rs +++ b/src/collection/ref.rs @@ -257,10 +257,10 @@ impl<'a, L: Lockable> RefLockCollection<'a, L> { /// *guard.0 += 1; /// *guard.1 = "1"; /// ``` - pub fn lock<'key: 'a, Key: Keyable + 'key>( - &'a self, + pub fn lock<'g, 'key: 'g, Key: Keyable + 'key>( + &'g self, key: Key, - ) -> LockGuard<'key, L::Guard<'a>, Key> { + ) -> LockGuard<'key, L::Guard<'g>, Key> { let guard = unsafe { // safety: we have the thread key self.raw_lock(); @@ -306,10 +306,10 @@ impl<'a, L: Lockable> RefLockCollection<'a, L> { /// }; /// /// ``` - pub fn try_lock<'key: 'a, Key: Keyable + 'key>( - &'a self, + pub fn try_lock<'g, 'key: 'a, Key: Keyable + 'key>( + &'g self, key: Key, - ) -> Result<LockGuard<'key, L::Guard<'a>, Key>, Key> { + ) -> Result<LockGuard<'key, L::Guard<'g>, Key>, Key> { let guard = unsafe { if !self.raw_try_lock() { return Err(key); @@ -345,7 +345,7 @@ impl<'a, L: Lockable> RefLockCollection<'a, L> { /// let key = RefLockCollection::<(Mutex<i32>, Mutex<&str>)>::unlock(guard); /// ``` #[allow(clippy::missing_const_for_fn)] - pub fn unlock<'key: 'a, Key: Keyable + 'key>(guard: LockGuard<'key, L::Guard<'a>, Key>) -> Key { + pub fn unlock<'g, 'key, Key: Keyable + 'key>(guard: LockGuard<'key, L::Guard<'g>, Key>) -> Key { drop(guard.guard); guard.key } @@ -372,10 +372,10 @@ impl<'a, L: Sharable> RefLockCollection<'a, L> { /// assert_eq!(*guard.0, 0); /// assert_eq!(*guard.1, ""); /// ``` - pub fn read<'key: 'a, Key: Keyable + 'key>( - &'a self, + pub fn read<'g, 'key: 'g, Key: Keyable + 'key>( + &'g self, key: Key, - ) -> LockGuard<'key, L::ReadGuard<'a>, Key> { + ) -> LockGuard<'key, L::ReadGuard<'g>, Key> { unsafe { // safety: we have the thread key self.raw_read(); @@ -420,10 +420,10 @@ impl<'a, L: Sharable> RefLockCollection<'a, L> { /// }; /// /// ``` - pub fn try_read<'key: 'a, Key: Keyable + 'key>( - &'a self, + pub fn try_read<'g, 'key: 'g, Key: Keyable + 'key>( + &'g self, key: Key, - ) -> Option<LockGuard<'key, L::ReadGuard<'a>, Key>> { + ) -> Option<LockGuard<'key, L::ReadGuard<'g>, Key>> { let guard = unsafe { // safety: we have the thread key if !self.raw_try_read() { diff --git a/src/collection/utils.rs b/src/collection/utils.rs index 7f29037..d6d50f4 100644 --- a/src/collection/utils.rs +++ b/src/collection/utils.rs @@ -109,7 +109,7 @@ pub unsafe fn attempt_to_recover_reads_from_panic(locked: &[&dyn RawLock]) { handle_unwind( || { // safety: the caller assumes these are already locked - locked.iter().for_each(|lock| lock.raw_unlock()); + locked.iter().for_each(|lock| lock.raw_unlock_read()); }, // if we get another panic in here, we'll just have to poison what remains || locked.iter().for_each(|l| l.poison()), |
