From 055e6fd92326e4796dccd13948b400719f65b546 Mon Sep 17 00:00:00 2001 From: Mica White Date: Sat, 7 Feb 2026 13:16:39 -0500 Subject: Finish documentation --- src/collection/retry.rs | 134 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) (limited to 'src/collection/retry.rs') diff --git a/src/collection/retry.rs b/src/collection/retry.rs index c887405..4a5df6e 100755 --- a/src/collection/retry.rs +++ b/src/collection/retry.rs @@ -534,6 +534,36 @@ impl RetryingLockCollection { (!contains_duplicates(&data)).then_some(unsafe { Self::new_unchecked(data) }) } + /// Acquires an exclusive lock, blocking until it is safe to do so, and then + /// unlocks after the provided function returns. + /// + /// This function is useful to ensure that the data is never accidentally + /// locked forever by leaking the guard. Even if the function panics, this + /// function will gracefully notice the panic, and unlock. This function + /// provides no guarantees with respect to the ordering of whether contentious + /// readers or writers will acquire the lock first. + /// + /// # Panics + /// + /// This function will panic if the provided function also panics. However, + /// the collection will be safely unlocked in this case, allowing the + /// collection to be locked again later. + /// + /// # Example + /// + /// ``` + /// use happylock::{ThreadKey, Mutex}; + /// use happylock::collection::RetryingLockCollection; + /// + /// let mut key = ThreadKey::get().unwrap(); + /// let data = (Mutex::new(0), Mutex::new("")); + /// let lock = RetryingLockCollection::new(data); + /// + /// lock.scoped_lock(&mut key, |(number, string)| { + /// *number += 1; + /// *string = "1"; + /// }); + /// ``` pub fn scoped_lock<'a, R>( &'a self, key: impl Keyable, @@ -542,6 +572,43 @@ impl RetryingLockCollection { scoped_write(self, key, f) } + /// Attempts to acquire an exclusive lock to the underlying data without + /// blocking, and then unlocks once the provided function returns. + /// + /// This function implements a non-blocking variant of [`scoped_lock`]. + /// Unlike `scoped_lock`, if the lock collection is not already unlocked, then + /// the provided function will not run, and the given [`Keyable`] is returned. + /// This method does not provide any guarantees with respect to the ordering + /// of whether contentious readers or writers will acquire the lock first. + /// + /// # Errors + /// + /// If any of the locks in the collection are already locked, then the + /// provided function will not run. `Err` is returned with the given key. + /// + /// # Panics + /// + /// This function will panic if the provided function also panics. However, + /// the collection will be safely unlocked in this case, allowing the + /// collection to be locked again later. + /// + /// # Example + /// + /// ``` + /// use happylock::{ThreadKey, Mutex}; + /// use happylock::collection::RetryingLockCollection; + /// + /// let mut key = ThreadKey::get().unwrap(); + /// let data = (Mutex::new(0), Mutex::new("")); + /// let lock = RetryingLockCollection::new(data); + /// + /// lock.scoped_try_lock(&mut key, |(number, string)| { + /// *number += 1; + /// *string = "1"; + /// }).expect("This lock has not yet been locked"); + /// ``` + /// + /// [`scoped_lock`]: RetryingLockCollection::scoped_lock pub fn scoped_try_lock<'a, Key: Keyable, R>( &'a self, key: Key, @@ -653,6 +720,36 @@ impl RetryingLockCollection { } impl RetryingLockCollection { + /// Acquires a shared lock, blocking until it is safe to do so, and then + /// unlocks after the provided function returns. + /// + /// This function is useful to ensure that the data is never accidentally + /// locked forever by leaking the guard. Even if the function panics, this + /// function will gracefully notice the panic, and unlock. This function + /// provides no guarantees with respect to the ordering of whether contentious + /// readers or writers will acquire the lock first. + /// + /// # Panics + /// + /// This function will panic if the provided function also panics. However, + /// the collection will be safely unlocked in this case, allowing the + /// collection to be locked again later. + /// + /// # Example + /// + /// ``` + /// use happylock::{ThreadKey, RwLock}; + /// use happylock::collection::RetryingLockCollection; + /// + /// let mut key = ThreadKey::get().unwrap(); + /// let data = (RwLock::new(0), RwLock::new("")); + /// let lock = RetryingLockCollection::new(data); + /// + /// lock.scoped_read(&mut key, |(number, string)| { + /// assert_eq!(*number, 0); + /// assert_eq!(*string, ""); + /// }); + /// ``` pub fn scoped_read<'a, R>( &'a self, key: impl Keyable, @@ -661,6 +758,43 @@ impl RetryingLockCollection { scoped_read(self, key, f) } + /// Attempts to acquire an exclusive lock to the underlying data without + /// blocking, and then unlocks once the provided function returns. + /// + /// This function implements a non-blocking variant of [`scoped_read`]. + /// Unlike `scoped_read`, if the lock collection is exclusively locked, then + /// the provided function will not run, and the given [`Keyable`] is returned. + /// This method does not provide any guarantees with respect to the ordering + /// of whether contentious readers or writers will acquire the lock first. + /// + /// # Errors + /// + /// If any of the locks in the collection are already exclusively locked, then + /// the provided function will not run. `Err` is returned with the given key. + /// + /// # Panics + /// + /// This function will panic if the provided function also panics. However, + /// the collection will be safely unlocked in this case, allowing the + /// collection to be locked again later. + /// + /// # Example + /// + /// ``` + /// use happylock::{ThreadKey, RwLock}; + /// use happylock::collection::RetryingLockCollection; + /// + /// let mut key = ThreadKey::get().unwrap(); + /// let data = (RwLock::new(0), RwLock::new("")); + /// let lock = RetryingLockCollection::new(data); + /// + /// lock.scoped_try_read(&mut key, |(number, string)| { + /// assert_eq!(*number, 0); + /// assert_eq!(*string, ""); + /// }).expect("This lock has not yet been locked"); + /// ``` + /// + /// [`scoped_read`]: RetryingLockCollection::scoped_read pub fn scoped_try_read<'a, Key: Keyable, R>( &'a self, key: Key, -- cgit v1.2.3