From fe67aa262f1b04fb6c38683d9221c3a2fafcc35a Mon Sep 17 00:00:00 2001 From: Mica White Date: Sun, 10 Mar 2024 20:21:00 -0400 Subject: Reorganization --- src/collection/collection.rs | 208 +++++++++++++++++++++++++++++++++++++++++++ src/collection/guard.rs | 19 ++++ 2 files changed, 227 insertions(+) create mode 100644 src/collection/collection.rs create mode 100644 src/collection/guard.rs (limited to 'src/collection') diff --git a/src/collection/collection.rs b/src/collection/collection.rs new file mode 100644 index 0000000..eb3bb69 --- /dev/null +++ b/src/collection/collection.rs @@ -0,0 +1,208 @@ +use std::marker::PhantomData; + +use crate::{key::Keyable, Lockable, OwnedLockable}; + +use super::{LockCollection, LockGuard}; + +/// returns `true` if the list contains a duplicate +#[must_use] +fn contains_duplicates(l: &[usize]) -> bool { + for i in 0..l.len() { + for j in (i + 1)..l.len() { + if l[i] == l[j] { + return true; + } + } + } + + false +} + +impl<'a, L: OwnedLockable<'a>> From for LockCollection { + fn from(value: L) -> Self { + Self::new(value) + } +} + +impl<'a, L: OwnedLockable<'a>> AsRef for LockCollection { + fn as_ref(&self) -> &L { + &self.collection + } +} + +impl<'a, L: OwnedLockable<'a>> AsMut for LockCollection { + fn as_mut(&mut self) -> &mut L { + &mut self.collection + } +} + +impl<'a, L: OwnedLockable<'a>> AsRef for LockCollection { + fn as_ref(&self) -> &Self { + self + } +} + +impl<'a, L: OwnedLockable<'a>> AsMut for LockCollection { + fn as_mut(&mut self) -> &mut Self { + self + } +} + +impl IntoIterator for LockCollection { + type Item = L::Item; + type IntoIter = L::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.collection.into_iter() + } +} + +impl<'a, L> IntoIterator for &'a LockCollection +where + &'a L: IntoIterator, +{ + type Item = <&'a L as IntoIterator>::Item; + type IntoIter = <&'a L as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.collection.into_iter() + } +} + +impl<'a, L> IntoIterator for &'a mut LockCollection +where + &'a mut L: IntoIterator, +{ + type Item = <&'a mut L as IntoIterator>::Item; + type IntoIter = <&'a mut L as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.collection.into_iter() + } +} + +impl<'a, L: OwnedLockable<'a>, I: FromIterator + OwnedLockable<'a>> FromIterator + for LockCollection +{ + fn from_iter>(iter: T) -> Self { + let iter: I = iter.into_iter().collect(); + Self::new(iter) + } +} + +impl<'a, E: OwnedLockable<'a> + Extend, L: OwnedLockable<'a>> Extend for LockCollection { + fn extend>(&mut self, iter: T) { + self.collection.extend(iter) + } +} + +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. + #[must_use] + 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. + #[must_use] + pub const fn new_ref(collection: &L) -> LockCollection<&L> { + LockCollection { collection } + } +} + +impl LockCollection { + /// Creates a new collections of locks. + /// + /// # Safety + /// + /// This results in undefined behavior if any locks are presented twice + /// within this collection. + #[must_use] + pub const unsafe fn new_unchecked(collection: L) -> Self { + Self { 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. + /// + /// # 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. + #[must_use] + pub fn try_new(collection: L) -> Option { + let ptrs = collection.get_ptrs(); + if contains_duplicates(&ptrs) { + return None; + } + + Some(Self { collection }) + } + + /// Locks the lockable type and returns a guard that can be used to access + /// the underlying data. + pub fn lock<'key: 'a, Key: Keyable + 'key>(&'a self, key: Key) -> LockGuard<'a, 'key, L, Key> { + LockGuard { + // safety: we have the thread's key + guard: unsafe { self.collection.lock() }, + key, + _phantom: PhantomData, + } + } + + /// Attempts to lock the guard without blocking. + /// + /// If successful, this method returns a guard that can be used to access + /// the data. Otherwise, `None` is returned. + pub fn try_lock<'key: 'a, Key: Keyable + 'key>( + &'a self, + key: Key, + ) -> Option> { + // safety: we have the thread's key + unsafe { self.collection.try_lock() }.map(|guard| LockGuard { + guard, + key, + _phantom: PhantomData, + }) + } + + /// Unlocks the underlying lockable data type, returning the key that's + /// associated with it. + #[allow(clippy::missing_const_for_fn)] + pub fn unlock<'key: 'a, Key: Keyable + 'key>(guard: LockGuard<'a, 'key, L, Key>) -> Key { + drop(guard.guard); + guard.key + } +} + +impl<'a, L: 'a> LockCollection +where + &'a L: IntoIterator, +{ + /// Returns an iterator over references to each value in the collection. + pub fn iter(&'a self) -> <&'a L as IntoIterator>::IntoIter { + self.into_iter() + } +} + +impl<'a, L: 'a> LockCollection +where + &'a mut L: IntoIterator, +{ + /// Returns an iterator over mutable references to each value in the + /// collection. + pub fn iter_mut(&'a mut self) -> <&'a mut L as IntoIterator>::IntoIter { + self.into_iter() + } +} diff --git a/src/collection/guard.rs b/src/collection/guard.rs new file mode 100644 index 0000000..110a935 --- /dev/null +++ b/src/collection/guard.rs @@ -0,0 +1,19 @@ +use std::ops::{Deref, DerefMut}; + +use crate::{key::Keyable, Lockable}; + +use super::LockGuard; + +impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> Deref for LockGuard<'a, 'key, L, Key> { + type Target = L::Output; + + fn deref(&self) -> &Self::Target { + &self.guard + } +} + +impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> DerefMut for LockGuard<'a, 'key, L, Key> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.guard + } +} -- cgit v1.2.3