Skip to main content

rustalign_concurrency/
thread_safe.rs

1//! Thread-safe RAII lock guard
2//!
3//! This matches the C++ ThreadSafe class that obtains a lock
4//! upon construction and releases it upon destruction.
5
6use std::sync::{Mutex, MutexGuard};
7
8/// RAII wrapper for mutex locks
9///
10/// This matches the C++ ThreadSafe class which obtains
11/// a lock upon construction and releases it upon destruction.
12pub struct ThreadSafe<'a, T>
13where
14    T: ?Sized,
15{
16    guard: MutexGuard<'a, T>,
17}
18
19impl<'a, T> ThreadSafe<'a, T> {
20    /// Lock a mutex and create a ThreadSafe guard
21    pub fn new(mutex: &'a Mutex<T>) -> Self {
22        let guard = mutex.lock().unwrap_or_else(|e| {
23            panic!("Failed to lock mutex: {}", e);
24        });
25        Self { guard }
26    }
27
28    /// Get a mutable reference to the guarded data
29    pub fn get(&mut self) -> &mut T {
30        &mut self.guard
31    }
32
33    /// Get an immutable reference to the guarded data
34    pub fn get_const(&self) -> &T {
35        &self.guard
36    }
37}
38
39impl<'a, T> std::ops::Deref for ThreadSafe<'a, T> {
40    type Target = T;
41
42    fn deref(&self) -> &Self::Target {
43        &self.guard
44    }
45}
46
47impl<'a, T> std::ops::DerefMut for ThreadSafe<'a, T> {
48    fn deref_mut(&mut self) -> &mut Self::Target {
49        &mut self.guard
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_thread_safe() {
59        let mutex = Mutex::new(42);
60        {
61            let mut safe = ThreadSafe::new(&mutex);
62            assert_eq!(*safe, 42);
63            *safe = 100;
64        }
65        assert_eq!(*mutex.lock().unwrap(), 100);
66    }
67}