From 61d709c211132adcc5158ded77c17d690ad5f8da Mon Sep 17 00:00:00 2001 From: Mica White Date: Sun, 10 Mar 2024 11:08:50 -0400 Subject: OwnedLockable --- src/collection.rs | 38 +++++++++++++++++++++++++++++++++----- src/lockable.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/collection.rs b/src/collection.rs index 4b24a67..34de620 100644 --- a/src/collection.rs +++ b/src/collection.rs @@ -3,13 +3,16 @@ use std::{ ops::{Deref, DerefMut}, }; -use crate::{key::Keyable, lockable::Lockable}; +use crate::{ + key::Keyable, + lockable::{Lockable, OwnedLockable}, +}; /// returns `true` if the list contains a duplicate fn contains_duplicates(l: &[usize]) -> bool { for i in 0..l.len() { - for j in 0..l.len() { - if i != j && l[i] == l[j] { + for j in (i + 1)..l.len() { + if l[i] == l[j] { return true; } } @@ -46,11 +49,36 @@ impl LockCollection { } } +impl<'a, L: OwnedLockable<'a>> LockCollection { + /// Creates a new collection of owned locks. + /// + /// Because the locks are owned, there's no need to do any checks for + /// duplicate values. + pub const fn new(collection: L) -> Self { + Self { collection } + } + + /// Creates a new collection of owned locks. + /// + /// Because the locks are owned, there's no need to do any checks for + /// duplicate values. + pub const fn new_ref(collection: &L) -> LockCollection<&L> { + LockCollection { collection } + } +} + impl<'a, L: Lockable<'a>> LockCollection { /// Creates a new collection of locks. /// - /// This returns `None` if any locks are found twice in the given collection. - pub fn new(collection: L) -> Option { + /// This returns `None` if any locks are found twice in the given + /// collection. + /// + /// # Performance + /// + /// This does a check at runtime to make sure that the collection contains + /// no two copies of the same lock. This is an `O(n^2)` operation. Prefer + /// [`LockCollection::new`] or [`LockCollection::new_ref`] instead. + pub fn try_new(collection: L) -> Option { let ptrs = collection.get_ptrs(); if contains_duplicates(&ptrs) { return None; diff --git a/src/lockable.rs b/src/lockable.rs index ddcc1c8..3c217c4 100644 --- a/src/lockable.rs +++ b/src/lockable.rs @@ -29,6 +29,15 @@ mod sealed { impl<'a, T: Lockable<'a>> Sealed for Vec {} } +/// A type that may be locked and unlocked, and is known to be the only valid +/// instance of the lock. +/// +/// # Safety +/// +/// There must not be any two values which can unlock the value at the same +/// time, i.e., this must either be an owned value or a mutable reference. +pub unsafe trait OwnedLockable<'a>: Lockable<'a> {} + /// A type that may be locked and unlocked /// /// # Safety @@ -102,6 +111,8 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &mut T { } } +unsafe impl<'a, T: OwnedLockable<'a>> OwnedLockable<'a> for &mut T {} + unsafe impl<'a, T: 'a, R: RawMutex + 'a> Lockable<'a> for Mutex { type Output = MutexRef<'a, T, R>; @@ -134,6 +145,10 @@ unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for RwLock { } } +unsafe impl<'a, T: 'a, R: RawMutex + 'a> OwnedLockable<'a> for Mutex {} + +unsafe impl<'a, T: 'a, R: RawRwLock + 'a> OwnedLockable<'a> for RwLock {} + unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for ReadLock<'a, T, R> { type Output = RwLockReadRef<'a, T, R>; @@ -439,6 +454,43 @@ unsafe impl< } } +unsafe impl<'a, A: OwnedLockable<'a>> OwnedLockable<'a> for (A,) {} +unsafe impl<'a, A: OwnedLockable<'a>, B: OwnedLockable<'a>> OwnedLockable<'a> for (A, B) {} +unsafe impl<'a, A: OwnedLockable<'a>, B: OwnedLockable<'a>, C: OwnedLockable<'a>> OwnedLockable<'a> + for (A, B, C) +{ +} +unsafe impl< + 'a, + A: OwnedLockable<'a>, + B: OwnedLockable<'a>, + C: OwnedLockable<'a>, + D: OwnedLockable<'a>, + > OwnedLockable<'a> for (A, B, C, D) +{ +} +unsafe impl< + 'a, + A: OwnedLockable<'a>, + B: OwnedLockable<'a>, + C: OwnedLockable<'a>, + D: OwnedLockable<'a>, + E: OwnedLockable<'a>, + > OwnedLockable<'a> for (A, B, C, D, E) +{ +} +unsafe impl< + 'a, + A: OwnedLockable<'a>, + B: OwnedLockable<'a>, + C: OwnedLockable<'a>, + D: OwnedLockable<'a>, + E: OwnedLockable<'a>, + F: OwnedLockable<'a>, + > OwnedLockable<'a> for (A, B, C, D, E, F) +{ +} + unsafe impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] { type Output = [T::Output; N]; @@ -554,3 +606,6 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec { Some(outputs) } } + +unsafe impl<'a, T: OwnedLockable<'a>, const N: usize> OwnedLockable<'a> for [T; N] {} +unsafe impl<'a, T: OwnedLockable<'a>> OwnedLockable<'a> for Vec {} -- cgit v1.2.3