txn_lock/
lib.rs

1//! Utilities to support transactional versioning.
2//!
3//! General-purpose locks and usage examples are provided
4//! in the [`map`], [`queue`], [`scalar`], and [`set`] modules.
5//!
6//! More complex transaction locks (e.g. for a relational database) can be constructed using
7//! the [`semaphore`] module.
8
9pub mod map;
10pub mod queue;
11pub mod scalar;
12pub mod semaphore;
13pub mod set;
14
15mod guard;
16mod range;
17
18use std::fmt;
19
20/// An error which may occur when attempting to acquire a transactional lock
21#[derive(Clone, Eq, PartialEq)]
22pub enum Error {
23    /// Cannot acquire a write lock because the transaction is already committed
24    Committed,
25
26    /// Cannot write to the requested range because it's already been locked in the future
27    Conflict,
28
29    /// Cannot read or write to the requested range because it's already been finalized
30    Outdated,
31
32    /// Unable to acquire a transactional lock synchronously
33    WouldBlock,
34
35    /// An error occurred in a background task
36    Background(String),
37}
38
39impl fmt::Display for Error {
40    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41        match self {
42            Self::Committed => f.write_str("cannot acquire an exclusive lock after committing"),
43            Self::Conflict => {
44                f.write_str("there is a conflicting transactional lock on this resource")
45            }
46            Self::Outdated => f.write_str("the value has already been finalized"),
47            Self::WouldBlock => f.write_str("synchronous lock acquisition failed"),
48            Self::Background(cause) => write!(f, "an error occured in a background task: {cause}"),
49        }
50    }
51}
52
53impl fmt::Debug for Error {
54    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55        fmt::Display::fmt(self, f)
56    }
57}
58
59impl std::error::Error for Error {}
60
61impl From<tokio::task::JoinError> for Error {
62    fn from(cause: tokio::task::JoinError) -> Self {
63        Self::Background(cause.to_string())
64    }
65}
66
67impl From<tokio::sync::AcquireError> for Error {
68    fn from(_: tokio::sync::AcquireError) -> Self {
69        Self::Outdated
70    }
71}
72
73impl From<tokio::sync::TryAcquireError> for Error {
74    fn from(cause: tokio::sync::TryAcquireError) -> Self {
75        match cause {
76            tokio::sync::TryAcquireError::Closed => Error::Outdated,
77            tokio::sync::TryAcquireError::NoPermits => Error::WouldBlock,
78        }
79    }
80}
81
82type Result<T> = std::result::Result<T, Error>;