From 9eec9ab94bbe5c9fbd52d5bbf393fe1ddcc6fc26 Mon Sep 17 00:00:00 2001 From: Mica White Date: Thu, 26 Dec 2024 12:06:47 -0500 Subject: Documentation --- src/rwlock/read_lock.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ src/rwlock/rwlock.rs | 22 ++++++++++++-- src/rwlock/write_lock.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 169 insertions(+), 4 deletions(-) (limited to 'src/rwlock') diff --git a/src/rwlock/read_lock.rs b/src/rwlock/read_lock.rs index d719a50..ae593e2 100644 --- a/src/rwlock/read_lock.rs +++ b/src/rwlock/read_lock.rs @@ -87,6 +87,34 @@ impl<'l, T, R> ReadLock<'l, T, R> { impl ReadLock<'_, T, R> { /// Locks the underlying [`RwLock`] with shared read access, blocking the /// current thread until it can be acquired. + /// + /// The calling thread will be blocked until there are no more writers + /// which hold the lock. There may be other readers currently inside the + /// lock when this method returns. + /// + /// Returns an RAII guard which will release this thread's shared access + /// once it is dropped. + /// + /// Because this method takes a [`ThreadKey`], it's not possible for this + /// method to cause a deadlock. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::thread; + /// use happylock::{RwLock, ThreadKey}; + /// use happylock::rwlock::ReadLock; + /// + /// let key = ThreadKey::get().unwrap(); + /// let lock: &'static mut RwLock<_> = Box::leak(Box::new(RwLock::new(1))); + /// let reader = ReadLock::new(&lock); + /// + /// let n = reader.lock(key); + /// assert_eq!(*n, 1); + /// ``` + /// + /// [`ThreadKey`]: `crate::ThreadKey` pub fn lock<'s, 'key: 's, Key: Keyable + 'key>( &'s self, key: Key, @@ -96,6 +124,35 @@ impl ReadLock<'_, T, R> { /// Attempts to acquire the underlying [`RwLock`] with shared read access /// without blocking. + /// + /// 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. + /// + /// This function does not provide any guarantees with respect to the + /// ordering of whether contentious readers or writers will acquire the + /// lock first. + /// + /// # Errors + /// + /// If the `RwLock` could not be acquired because it was already locked + /// exclusively, then an error will be returned containing the given key. + /// + /// # Examples + /// + /// ``` + /// use happylock::{RwLock, ThreadKey}; + /// use happylock::rwlock::ReadLock; + /// + /// let key = ThreadKey::get().unwrap(); + /// let lock = RwLock::new(1); + /// let reader = ReadLock::new(&lock); + /// + /// match reader.try_lock(key) { + /// Ok(n) => assert_eq!(*n, 1), + /// Err(_) => unreachable!(), + /// }; + /// ``` pub fn try_lock<'s, 'key: 's, Key: Keyable + 'key>( &'s self, key: Key, @@ -111,6 +168,25 @@ impl ReadLock<'_, T, R> { /// Immediately drops the guard, and consequently releases the shared lock /// on the underlying [`RwLock`]. + /// + /// This function is equivalent to calling [`drop`] on the guard, except + /// that it returns the key that was used to create it. Alternately, the + /// guard will be automatically dropped when it goes out of scope. + /// + /// # Examples + /// + /// ``` + /// use happylock::{RwLock, ThreadKey}; + /// use happylock::rwlock::ReadLock; + /// + /// let key = ThreadKey::get().unwrap(); + /// let lock = RwLock::new(0); + /// let reader = ReadLock::new(&lock); + /// + /// let mut guard = reader.lock(key); + /// assert_eq!(*guard, 0); + /// let key = ReadLock::unlock(guard); + /// ``` pub fn unlock<'key, Key: Keyable + 'key>(guard: RwLockReadGuard<'_, 'key, T, Key, R>) -> Key { RwLock::unlock_read(guard) } diff --git a/src/rwlock/rwlock.rs b/src/rwlock/rwlock.rs index 6432128..a249675 100644 --- a/src/rwlock/rwlock.rs +++ b/src/rwlock/rwlock.rs @@ -277,10 +277,19 @@ impl RwLock { /// Attempts to acquire this `RwLock` with shared read access without /// blocking. /// - /// If the access could not be granted at this time, then `None` is + /// 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. /// + /// This function does not provide any guarantees with respect to the + /// ordering of whether contentious readers or writers will acquire the + /// lock first. + /// + /// # Errors + /// + /// If the `RwLock` could not be acquired because it was already locked + /// exclusively, then an error will be returned containing the given key. + /// /// # Examples /// /// ``` @@ -351,8 +360,10 @@ impl RwLock { /// let key = ThreadKey::get().unwrap(); /// let lock = RwLock::new(1); /// - /// let mut n = lock.write(key); - /// *n += 2; + /// match lock.try_write(key) { + /// Ok(n) => assert_eq!(*n, 1), + /// Err(_) => unreachable!(), + /// }; /// ``` /// /// [`ThreadKey`]: `crate::ThreadKey` @@ -378,6 +389,11 @@ impl RwLock { /// ordering of whether contentious readers or writers will acquire the /// lock first. /// + /// # Errors + /// + /// If the `RwLock` could not be acquired because it was already locked, + /// then an error will be returned containing the given key. + /// /// # Examples /// /// ``` diff --git a/src/rwlock/write_lock.rs b/src/rwlock/write_lock.rs index e9be750..ff00c06 100644 --- a/src/rwlock/write_lock.rs +++ b/src/rwlock/write_lock.rs @@ -81,6 +81,31 @@ impl<'l, T, R> WriteLock<'l, T, R> { impl WriteLock<'_, T, R> { /// Locks the underlying [`RwLock`] with exclusive write access, blocking /// the current until it can be acquired. + /// + /// This function will not return while other writers or readers currently + /// have access to the lock. + /// + /// Returns an RAII guard which will drop the write access of this `RwLock` + /// when dropped. + /// + /// Because this method takes a [`ThreadKey`], it's not possible for this + /// method to cause a deadlock. + /// + /// # Examples + /// + /// ``` + /// use happylock::{ThreadKey, RwLock}; + /// use happylock::rwlock::WriteLock; + /// + /// let key = ThreadKey::get().unwrap(); + /// let lock = RwLock::new(1); + /// let writer = WriteLock::new(&lock); + /// + /// let mut n = writer.lock(key); + /// *n += 2; + /// ``` + /// + /// [`ThreadKey`]: `crate::ThreadKey` pub fn lock<'s, 'key: 's, Key: Keyable + 'key>( &'s self, key: Key, @@ -89,6 +114,35 @@ impl WriteLock<'_, T, R> { } /// Attempts to lock the underlying [`RwLock`] with exclusive write access. + /// + /// This function does not block. If the lock could not be acquired at this + /// time, then `None` is returned. Otherwise, an RAII guard is returned + /// which will release the lock when it is dropped. + /// + /// This function does not provide any guarantees with respect to the + /// ordering of whether contentious readers or writers will acquire the + /// lock first. + /// + /// # Errors + /// + /// If the [`RwLock`] could not be acquired because it was already locked, + /// then an error will be returned containing the given key. + /// + /// # Examples + /// + /// ``` + /// use happylock::{RwLock, ThreadKey}; + /// use happylock::rwlock::WriteLock; + /// + /// let key = ThreadKey::get().unwrap(); + /// let lock = RwLock::new(1); + /// let writer = WriteLock::new(&lock); + /// + /// match writer.try_lock(key) { + /// Ok(n) => assert_eq!(*n, 1), + /// Err(_) => unreachable!(), + /// }; + /// ``` pub fn try_lock<'s, 'key: 's, Key: Keyable + 'key>( &'s self, key: Key, @@ -100,7 +154,26 @@ impl WriteLock<'_, T, R> { // the referenced `RwLock`. /// Immediately drops the guard, and consequently releases the exclusive - /// lock. + /// lock on the underlying [`RwLock`]. + /// + /// This function is equivalent to calling [`drop`] on the guard, except + /// that it returns the key that was used to create it. Alternately, the + /// guard will be automatically dropped when it goes out of scope. + /// + /// # Examples + /// + /// ``` + /// use happylock::{RwLock, ThreadKey}; + /// use happylock::rwlock::WriteLock; + /// + /// let key = ThreadKey::get().unwrap(); + /// let lock = RwLock::new(0); + /// let writer = WriteLock::new(&lock); + /// + /// let mut guard = writer.lock(key); + /// *guard += 20; + /// let key = WriteLock::unlock(guard); + /// ``` pub fn unlock<'key, Key: Keyable + 'key>(guard: RwLockWriteGuard<'_, 'key, T, Key, R>) -> Key { RwLock::unlock_write(guard) } -- cgit v1.2.3