summaryrefslogtreecommitdiff
path: root/src/poisonable.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/poisonable.rs')
-rw-r--r--src/poisonable.rs60
1 files changed, 54 insertions, 6 deletions
diff --git a/src/poisonable.rs b/src/poisonable.rs
index 49979e5..a492084 100644
--- a/src/poisonable.rs
+++ b/src/poisonable.rs
@@ -1,5 +1,3 @@
-#[cfg(not(panic = "unwind"))]
-use std::convert::Infallible;
use std::marker::PhantomData;
use std::sync::atomic::AtomicBool;
@@ -10,37 +8,87 @@ mod flag;
mod guard;
mod poisonable;
+/// A flag indicating if a lock is poisoned or not. The implementation differs
+/// depending on whether panics are set to unwind or abort.
#[derive(Debug, Default)]
struct PoisonFlag(#[cfg(panic = "unwind")] AtomicBool);
+/// A wrapper around [`Lockable`] types which will enable poisoning.
+///
+/// A lock is "poisoned" when the thread panics while holding the lock. Once a
+/// lock is poisoned, all other threads are unable to access the data by
+/// default, because the data may be tainted (some invariant of the data might
+/// not be upheld).
+///
+/// The [`lock`] and [`try_lock`] methods return a [`Result`] which indicates
+/// whether the lock has been poisoned or not. The [`PoisonError`] type has an
+/// [`into_inner`] method which will return the guard that normally would have
+/// been returned for a successful lock. This allows access to the data,
+/// despite the lock being poisoned.
+///
+/// Alternatively, there is also a [`clear_poison`] method, which should
+/// indicate that all invariants of the underlying data are upheld, so that
+/// subsequent calls may still return [`Ok`].
+///
+/// [`lock`]: `Poisonable::lock`
+/// [`try_lock`]: `Poisonable::try_lock`
+/// [`into_inner`]: `PoisonError::into_inner`
+/// [`clear_poison`]: `Poisonable::clear_poison`
#[derive(Debug, Default)]
pub struct Poisonable<L: Lockable + RawLock> {
inner: L,
poisoned: PoisonFlag,
}
-pub struct PoisonRef<'flag, G> {
+/// An RAII guard for a [`Poisonable`].
+///
+/// This is similar to a [`PoisonGuard`], except that it does not hold a
+/// [`Keyable`]
+///
+/// [`Keyable`]: `crate::Keyable`
+pub struct PoisonRef<'a, G> {
guard: G,
#[cfg(panic = "unwind")]
- flag: &'flag PoisonFlag,
+ flag: &'a PoisonFlag,
+ _phantom: PhantomData<&'a ()>,
}
-pub struct PoisonGuard<'flag, 'key, G, Key> {
- guard: PoisonRef<'flag, G>,
+/// An RAII guard for a [`Poisonable`].
+///
+/// This is created by calling methods like [`Poisonable::lock`].
+pub struct PoisonGuard<'a, 'key, G, Key> {
+ guard: PoisonRef<'a, G>,
key: Key,
_phantom: PhantomData<&'key ()>,
}
+/// A type of error which can be returned when acquiring a [`Poisonable`] lock.
pub struct PoisonError<Guard> {
guard: Guard,
}
+/// An enumeration of possible errors associated with
+/// [`TryLockPoisonableResult`] which can occur while trying to acquire a lock
+/// (i.e.: [`Poisonable::try_lock`]).
pub enum TryLockPoisonableError<'flag, 'key, G, Key: 'key> {
Poisoned(PoisonError<PoisonGuard<'flag, 'key, G, Key>>),
WouldBlock(Key),
}
+/// A type alias for the result of a lock method which can poisoned.
+///
+/// The [`Ok`] variant of this result indicates that the primitive was not
+/// poisoned, and the primitive was poisoned. Note that the [`Err`] variant
+/// *also* carries the associated guard, and it can be acquired through the
+/// [`into_inner`] method.
+///
+/// [`into_inner`]: `PoisonError::into_inner`
pub type PoisonResult<Guard> = Result<Guard, PoisonError<Guard>>;
+/// A type alias for the result of a nonblocking locking method.
+///
+/// For more information, see [`PoisonResult`]. A `TryLockPoisonableResult`
+/// doesn't necessarily hold the associated guard in the [`Err`] type as the
+/// lock might not have been acquired for other reasons.
pub type TryLockPoisonableResult<'flag, 'key, G, Key> =
Result<PoisonGuard<'flag, 'key, G, Key>, TryLockPoisonableError<'flag, 'key, G, Key>>;