summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/collection/boxed.rs130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/collection/boxed.rs b/src/collection/boxed.rs
index 85ec34f..234fa07 100755
--- a/src/collection/boxed.rs
+++ b/src/collection/boxed.rs
@@ -361,6 +361,35 @@ impl<L: Lockable> BoxedLockCollection<L> {
}
}
+ /// 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::{LockCollection, ThreadKey, Mutex};
+ ///
+ /// let mut key = ThreadKey::get().unwrap();
+ /// let data = (Mutex::new(0), Mutex::new(""));
+ /// let lock = LockCollection::new(data);
+ ///
+ /// lock.scoped_lock(&mut key, |(number, string)| {
+ /// *number += 1;
+ /// *string = "1";
+ /// });
+ /// ```
pub fn scoped_lock<'a, R>(
&'a self,
key: impl Keyable,
@@ -369,6 +398,42 @@ impl<L: Lockable> BoxedLockCollection<L> {
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::{LockCollection, ThreadKey, Mutex};
+ ///
+ /// let mut key = ThreadKey::get().unwrap();
+ /// let data = (Mutex::new(0), Mutex::new(""));
+ /// let lock = LockCollection::new(data);
+ ///
+ /// lock.scoped_try_lock(&mut key, |(number, string)| {
+ /// *number += 1;
+ /// *string = "1";
+ /// }).expect("This lock has not yet been locked");
+ /// ```
+ ///
+ /// [`scoped_lock`]: BoxedLockCollection::scoped_lock
pub fn scoped_try_lock<'a, Key: Keyable, R>(
&'a self,
key: Key,
@@ -477,6 +542,35 @@ impl<L: Lockable> BoxedLockCollection<L> {
}
impl<L: Sharable> BoxedLockCollection<L> {
+ /// 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::{LockCollection, ThreadKey, Mutex};
+ ///
+ /// let mut key = ThreadKey::get().unwrap();
+ /// let data = (Mutex::new(0), Mutex::new(""));
+ /// let lock = LockCollection::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,
@@ -485,6 +579,42 @@ impl<L: Sharable> BoxedLockCollection<L> {
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::{LockCollection, ThreadKey, Mutex};
+ ///
+ /// let mut key = ThreadKey::get().unwrap();
+ /// let data = (Mutex::new(0), Mutex::new(""));
+ /// let lock = LockCollection::new(data);
+ ///
+ /// lock.scoped_try_read(&mut key, |(number, string)| {
+ /// *number += 1;
+ /// *string = "1";
+ /// }).expect("This lock has not yet been locked");
+ /// ```
+ ///
+ /// [`scoped_read`]: BoxedLockCollection::scoped_read
pub fn scoped_try_read<'a, Key: Keyable, R>(
&'a self,
key: Key,