From 9eec9ab94bbe5c9fbd52d5bbf393fe1ddcc6fc26 Mon Sep 17 00:00:00 2001 From: Mica White Date: Thu, 26 Dec 2024 12:06:47 -0500 Subject: Documentation --- src/collection/boxed.rs | 66 ++++++++++++++++++++++++++++++++------- src/collection/owned.rs | 66 +++++++++++++++++++++++++++++++++++---- src/collection/ref.rs | 41 ++++++++++++++++++++---- src/collection/retry.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 227 insertions(+), 29 deletions(-) (limited to 'src/collection') diff --git a/src/collection/boxed.rs b/src/collection/boxed.rs index c0cc294..7a84b2a 100644 --- a/src/collection/boxed.rs +++ b/src/collection/boxed.rs @@ -211,6 +211,23 @@ impl BoxedLockCollection { // references happening at the same time /// Gets an immutable reference to the underlying data + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, ThreadKey, LockCollection}; + /// + /// let data1 = Mutex::new(42); + /// let data2 = Mutex::new(""); + /// + /// // data1 and data2 refer to distinct mutexes, so this won't panic + /// let data = (&data1, &data2); + /// let lock = LockCollection::try_new(&data).unwrap(); + /// + /// let key = ThreadKey::get().unwrap(); + /// let guard = lock.child().0.lock(key); + /// assert_eq!(*guard, 42); + /// ``` #[must_use] pub fn child(&self) -> &L { unsafe { @@ -375,9 +392,14 @@ impl BoxedLockCollection { /// Attempts to lock the without blocking. /// - /// If successful, this method returns a guard that can be used to access - /// the data, and unlocks the data when it is dropped. Otherwise, `None` is - /// returned. + /// If the access could not be granted at this time, then `Err` is + /// returned. Otherwise, an RAII guard is returned which will release the + /// locks when it is dropped. + /// + /// # Errors + /// + /// If any locks in the collection are already locked, then an error + /// containing the given key is returned. /// /// # Examples /// @@ -480,9 +502,14 @@ impl BoxedLockCollection { /// Attempts to lock the without blocking, in such a way that other threads /// can still read from the collection. /// - /// If successful, this method returns a guard that can be used to access - /// the data immutably, and unlocks the data when it is dropped. Otherwise, - /// `None` is returned. + /// If the access could not be granted at this time, then `Err` is + /// returned. Otherwise, an RAII guard is returned which will release the + /// shared access when it is dropped. + /// + /// # Errors + /// + /// If any of the locks in the collection are already locked, then an error + /// is returned containing the given key. /// /// # Examples /// @@ -494,29 +521,29 @@ impl BoxedLockCollection { /// let lock = LockCollection::new(data); /// /// match lock.try_read(key) { - /// Some(mut guard) => { + /// Ok(mut guard) => { /// assert_eq!(*guard.0, 5); /// assert_eq!(*guard.1, "6"); /// }, - /// None => unreachable!(), + /// Err(_) => unreachable!(), /// }; /// /// ``` pub fn try_read<'g, 'key: 'g, Key: Keyable + 'key>( &'g self, key: Key, - ) -> Option, Key>> { + ) -> Result, Key>, Key> { let guard = unsafe { // safety: we have the thread key if !self.raw_try_read() { - return None; + return Err(key); } // safety: we've acquired the locks self.child().read_guard() }; - Some(LockGuard { + Ok(LockGuard { guard, key, _phantom: PhantomData, @@ -546,6 +573,23 @@ impl BoxedLockCollection { } } +impl BoxedLockCollection { + /// Consumes this `BoxedLockCollection`, returning the underlying data. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, LockCollection}; + /// + /// let mutex = LockCollection::new([Mutex::new(0), Mutex::new(0)]); + /// assert_eq!(mutex.into_inner(), [0, 0]); + /// ``` + #[must_use] + pub fn into_inner(self) -> ::Inner { + LockableIntoInner::into_inner(self) + } +} + impl<'a, L: 'a> BoxedLockCollection where &'a L: IntoIterator, diff --git a/src/collection/owned.rs b/src/collection/owned.rs index 3d6fa93..7436a6e 100644 --- a/src/collection/owned.rs +++ b/src/collection/owned.rs @@ -213,9 +213,14 @@ impl OwnedLockCollection { /// Attempts to lock the without blocking. /// - /// If successful, this method returns a guard that can be used to access - /// the data, and unlocks the data when it is dropped. Otherwise, `None` is - /// returned. + /// If the access could not be granted at this time, then `Err` is + /// returned. Otherwise, an RAII guard is returned which will release the + /// locks when it is dropped. + /// + /// # Errors + /// + /// If any of the locks in this collection are already locked, this returns + /// an error containing the given key. /// /// # Examples /// @@ -324,9 +329,14 @@ impl OwnedLockCollection { /// Attempts to lock the without blocking, in such a way that other threads /// can still read from the collection. /// - /// If successful, this method returns a guard that can be used to access - /// the data immutably, and unlocks the data when it is dropped. Otherwise, - /// `None` is returned. + /// If the access could not be granted at this time, then `Err` is + /// returned. Otherwise, an RAII guard is returned which will release the + /// shared access when it is dropped. + /// + /// # Errors + /// + /// If any of the locks in this collection can't be acquired, then an error + /// is returned containing the given key. /// /// # Examples /// @@ -415,18 +425,62 @@ impl OwnedLockCollection { self.data } + /// Gets a mutable reference to the underlying collection. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, ThreadKey}; + /// use happylock::collection::OwnedLockCollection; + /// + /// let data = (Mutex::new(42), Mutex::new("")); + /// let mut lock = OwnedLockCollection::new(data); + /// + /// let key = ThreadKey::get().unwrap(); + /// let mut inner = lock.child_mut(); + /// let guard = inner.0.get_mut(); + /// assert_eq!(*guard, 42); + /// ``` + #[must_use] pub fn child_mut(&mut self) -> &mut L { &mut self.data } } impl OwnedLockCollection { + /// Gets a mutable reference to the data behind this `OwnedLockCollection`. + /// + /// Since this call borrows the `OwnedLockCollection` mutably, no actual + /// locking needs to take place - the mutable borrow statically guarantees + /// no locks exist. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, LockCollection}; + /// use happylock::collection::OwnedLockCollection; + /// + /// let mut mutex = OwnedLockCollection::new([Mutex::new(0), Mutex::new(0)]); + /// assert_eq!(mutex.get_mut(), [&mut 0, &mut 0]); + /// ``` pub fn get_mut(&mut self) -> L::Inner<'_> { LockableGetMut::get_mut(self) } } impl OwnedLockCollection { + /// Consumes this `OwnedLockCollection`, returning the underlying data. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, LockCollection}; + /// use happylock::collection::OwnedLockCollection; + /// + /// let mutex = OwnedLockCollection::new([Mutex::new(0), Mutex::new(0)]); + /// assert_eq!(mutex.into_inner(), [0, 0]); + /// ``` + #[must_use] pub fn into_inner(self) -> L::Inner { LockableIntoInner::into_inner(self) } diff --git a/src/collection/ref.rs b/src/collection/ref.rs index a9c3579..1e17412 100644 --- a/src/collection/ref.rs +++ b/src/collection/ref.rs @@ -151,6 +151,25 @@ impl<'a, L: OwnedLockable> RefLockCollection<'a, L> { } impl RefLockCollection<'_, L> { + /// Gets an immutable reference to the underlying data + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, ThreadKey}; + /// use happylock::collection::RefLockCollection; + /// + /// let data1 = Mutex::new(42); + /// let data2 = Mutex::new(""); + /// + /// // data1 and data2 refer to distinct mutexes, so this won't panic + /// let data = (&data1, &data2); + /// let lock = RefLockCollection::try_new(&data).unwrap(); + /// + /// let key = ThreadKey::get().unwrap(); + /// let guard = lock.child().0.lock(key); + /// assert_eq!(*guard, 42); + /// ``` #[must_use] pub const fn child(&self) -> &L { self.data @@ -255,9 +274,14 @@ impl<'a, L: Lockable> RefLockCollection<'a, L> { /// Attempts to lock the without blocking. /// - /// If successful, this method returns a guard that can be used to access - /// the data, and unlocks the data when it is dropped. Otherwise, `None` is - /// returned. + /// If the access could not be granted at this time, then `Err` is + /// returned. Otherwise, an RAII guard is returned which will release the + /// locks when it is dropped. + /// + /// # Errors + /// + /// If any of the locks in the collection are already locked, then an error + /// is returned containing the given key. /// /// # Examples /// @@ -364,9 +388,14 @@ impl<'a, L: Sharable> RefLockCollection<'a, L> { /// Attempts to lock the without blocking, in such a way that other threads /// can still read from the collection. /// - /// If successful, this method returns a guard that can be used to access - /// the data immutably, and unlocks the data when it is dropped. Otherwise, - /// `None` is returned. + /// If the access could not be granted at this time, then `Err` is + /// returned. Otherwise, an RAII guard is returned which will release the + /// shared access when it is dropped. + /// + /// # Errors + /// + /// If any of the locks in the collection are already locked, then an error + /// is returned containing the given key. /// /// # Examples /// diff --git a/src/collection/retry.rs b/src/collection/retry.rs index 83842f8..db09ebf 100644 --- a/src/collection/retry.rs +++ b/src/collection/retry.rs @@ -422,10 +422,44 @@ impl RetryingLockCollection { Self { data } } + /// Gets an immutable reference to the underlying collection. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, ThreadKey}; + /// use happylock::collection::RetryingLockCollection; + /// + /// let data = (Mutex::new(42), Mutex::new("")); + /// let lock = RetryingLockCollection::new(data); + /// + /// let key = ThreadKey::get().unwrap(); + /// let inner = lock.child(); + /// let guard = inner.0.lock(key); + /// assert_eq!(*guard, 42); + /// ``` + #[must_use] pub const fn child(&self) -> &L { &self.data } + /// Gets a mutable reference to the underlying collection. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, ThreadKey}; + /// use happylock::collection::RetryingLockCollection; + /// + /// let data = (Mutex::new(42), Mutex::new("")); + /// let mut lock = RetryingLockCollection::new(data); + /// + /// let key = ThreadKey::get().unwrap(); + /// let mut inner = lock.child_mut(); + /// let guard = inner.0.get_mut(); + /// assert_eq!(*guard, 42); + /// ``` + #[must_use] pub fn child_mut(&mut self) -> &mut L { &mut self.data } @@ -515,9 +549,14 @@ impl RetryingLockCollection { /// Attempts to lock the without blocking. /// - /// If successful, this method returns a guard that can be used to access - /// the data, and unlocks the data when it is dropped. Otherwise, `None` is - /// returned. + /// If the access could not be granted at this time, then `Err` is + /// returned. Otherwise, an RAII guard is returned which will release the + /// locks when it is dropped. + /// + /// # Errors + /// + /// If any of the locks in the collection are already locked, then an error + /// is returned containing the given key. /// /// # Examples /// @@ -622,9 +661,14 @@ impl RetryingLockCollection { /// Attempts to lock the without blocking, in such a way that other threads /// can still read from the collection. /// - /// If successful, this method returns a guard that can be used to access - /// the data immutably, and unlocks the data when it is dropped. Otherwise, - /// `None` is returned. + /// If the access could not be granted at this time, then `Err` is + /// returned. Otherwise, an RAII guard is returned which will release the + /// shared access when it is dropped. + /// + /// # Errors + /// + /// If shared access cannot be acquired at this time, then an error is + /// returned containing the given key. /// /// # Examples /// @@ -685,12 +729,39 @@ impl RetryingLockCollection { } impl RetryingLockCollection { + /// Gets a mutable reference to the data behind this + /// `RetryingLockCollection`. + /// + /// Since this call borrows the `RetryingLockCollection` mutably, no actual + /// locking needs to take place - the mutable borrow statically guarantees + /// no locks exist. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, LockCollection}; + /// use happylock::collection::RetryingLockCollection; + /// + /// let mut mutex = RetryingLockCollection::new([Mutex::new(0), Mutex::new(0)]); + /// assert_eq!(mutex.get_mut(), [&mut 0, &mut 0]); + /// ``` pub fn get_mut(&mut self) -> L::Inner<'_> { LockableGetMut::get_mut(self) } } impl RetryingLockCollection { + /// Consumes this `RetryingLockCollection`, returning the underlying data. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, LockCollection}; + /// use happylock::collection::RetryingLockCollection; + /// + /// let mutex = RetryingLockCollection::new([Mutex::new(0), Mutex::new(0)]); + /// assert_eq!(mutex.into_inner(), [0, 0]); + /// ``` pub fn into_inner(self) -> L::Inner { LockableIntoInner::into_inner(self) } -- cgit v1.2.3