atagen

matrix-rust-sdk

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk.git
crates/matrix-sdk-common/src/locks.rsRust130 lines3.6 KB
1
// Copyright 2025 The Matrix.org Foundation C.I.C.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
//! Simplified locks hat panic instead of returning a `Result` when the lock is
16
//! poisoned.
17
18
use std::{
19
    fmt,
20
    sync::{Mutex as StdMutex, MutexGuard, RwLock as StdRwLock, RwLockReadGuard, RwLockWriteGuard},
21
};
22
23
use serde::{Deserialize, Serialize};
24
25
/// A wrapper around `std::sync::Mutex` that panics on poison.
26
///
27
/// This `Mutex` works similarly to the standard library's `Mutex`, except its
28
/// `lock` method does not return a `Result`. Instead, if the mutex is poisoned,
29
/// it will panic.
30
///
31
/// # Examples
32
///
33
/// ```
34
/// use matrix_sdk_common::locks::Mutex;
35
///
36
/// let mutex = Mutex::new(42);
37
///
38
/// {
39
///     let mut guard = mutex.lock();
40
///     *guard = 100;
41
/// }
42
///
43
/// assert_eq!(*mutex.lock(), 100);
44
/// ```
45
#[derive(Default)]
46
pub struct Mutex<T: ?Sized>(StdMutex<T>);
47
48
impl<T> Mutex<T> {
49
    /// Creates a new `Mutex` wrapping the given value.
50
    pub const fn new(t: T) -> Self {
51
        Self(StdMutex::new(t))
52
    }
53
}
54
55
impl<T: ?Sized> Mutex<T> {
56
    /// Acquires the lock, panicking if the lock is poisoned.
57
    ///
58
    /// This method blocks the current thread until the lock is acquired.
59
    pub fn lock(&self) -> MutexGuard<'_, T> {
60
        self.0.lock().expect("The Mutex should never be poisoned")
61
    }
62
}
63
64
impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
65
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66
        self.0.fmt(f)
67
    }
68
}
69
70
/// A wrapper around [`std::sync::RwLock`] that panics on poison.
71
///
72
/// This `RwLock` works similarly to the standard library's `RwLock`, except its
73
/// `read` and `write` methods do not return a `Result`. Instead, if the lock is
74
/// poisoned, it will panic.
75
///
76
/// # Examples
77
///
78
/// ```
79
/// use matrix_sdk_common::locks::RwLock;
80
///
81
/// let lock = RwLock::new(42);
82
///
83
/// {
84
///     let read_guard = lock.read();
85
///     assert_eq!(*read_guard, 42);
86
/// }
87
/// {
88
///     let mut write_guard = lock.write();
89
///     *write_guard = 100;
90
/// }
91
/// assert_eq!(*lock.read(), 100);
92
/// ```
93
#[derive(Default, Serialize, Deserialize)]
94
#[serde(transparent)]
95
pub struct RwLock<T: ?Sized>(StdRwLock<T>);
96
97
impl<T> RwLock<T> {
98
    /// Creates a new `RwLock` wrapping the given value.
99
    pub const fn new(t: T) -> Self {
100
        Self(StdRwLock::new(t))
101
    }
102
}
103
104
impl<T: ?Sized> RwLock<T> {
105
    /// Acquires a mutable write lock, panicking if the lock is poisoned.
106
    ///
107
    /// This method blocks the current thread until the lock is acquired.
108
    pub fn write(&self) -> RwLockWriteGuard<'_, T> {
109
        self.0.write().expect("The RwLock should never be poisoned")
110
    }
111
112
    /// Acquires a shared read lock, panicking if the lock is poisoned.
113
    ///
114
    /// This method blocks the current thread until the lock is acquired.
115
    pub fn read(&self) -> RwLockReadGuard<'_, T> {
116
        self.0.read().expect("The RwLock should never be poisoned")
117
    }
118
}
119
120
impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
121
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122
        self.0.fmt(f)
123
    }
124
}
125
126
impl<T> From<T> for RwLock<T> {
127
    fn from(value: T) -> Self {
128
        Self::new(value)
129
    }
130
}