Skip to main content

windjammer_runtime/
sync.rs

1//! Synchronization primitives
2//!
3//! Windjammer's sync module provides thread-safe synchronization primitives
4//! with simplified error handling and ergonomic APIs.
5
6pub use std::sync::{
7    mpsc, Arc, Condvar, Mutex, MutexGuard, Once, RwLock, RwLockReadGuard, RwLockWriteGuard,
8};
9
10/// Create a new Mutex
11pub fn mutex<T>(value: T) -> Mutex<T> {
12    Mutex::new(value)
13}
14
15/// Create a new RwLock
16pub fn rwlock<T>(value: T) -> RwLock<T> {
17    RwLock::new(value)
18}
19
20/// Create a new Arc
21pub fn arc<T>(value: T) -> Arc<T> {
22    Arc::new(value)
23}
24
25/// Create a new Arc<Mutex<T>>
26pub fn arc_mutex<T>(value: T) -> Arc<Mutex<T>> {
27    Arc::new(Mutex::new(value))
28}
29
30/// Create a new Arc<RwLock<T>>
31pub fn arc_rwlock<T>(value: T) -> Arc<RwLock<T>> {
32    Arc::new(RwLock::new(value))
33}
34
35/// Lock a mutex, panicking on poison
36pub fn lock<T>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
37    mutex.lock().expect("Mutex poisoned")
38}
39
40/// Try to lock a mutex
41pub fn try_lock<T>(mutex: &Mutex<T>) -> Option<MutexGuard<'_, T>> {
42    mutex.try_lock().ok()
43}
44
45/// Read lock an RwLock
46pub fn read<T>(rwlock: &RwLock<T>) -> RwLockReadGuard<'_, T> {
47    rwlock.read().expect("RwLock poisoned")
48}
49
50/// Write lock an RwLock
51pub fn write<T>(rwlock: &RwLock<T>) -> RwLockWriteGuard<'_, T> {
52    rwlock.write().expect("RwLock poisoned")
53}
54
55/// Try to read lock an RwLock
56pub fn try_read<T>(rwlock: &RwLock<T>) -> Option<RwLockReadGuard<'_, T>> {
57    rwlock.try_read().ok()
58}
59
60/// Try to write lock an RwLock
61pub fn try_write<T>(rwlock: &RwLock<T>) -> Option<RwLockWriteGuard<'_, T>> {
62    rwlock.try_write().ok()
63}
64
65/// Create a channel
66pub fn channel<T>() -> (mpsc::Sender<T>, mpsc::Receiver<T>) {
67    mpsc::channel()
68}
69
70/// Create a bounded channel
71pub fn sync_channel<T>(bound: usize) -> (mpsc::SyncSender<T>, mpsc::Receiver<T>) {
72    mpsc::sync_channel(bound)
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn test_mutex() {
81        let m = mutex(5);
82        {
83            let mut guard = lock(&m);
84            *guard = 10;
85        }
86        assert_eq!(*lock(&m), 10);
87    }
88
89    #[test]
90    fn test_rwlock() {
91        let rw = rwlock(String::from("hello"));
92
93        // Multiple readers
94        {
95            let r1 = read(&rw);
96            let r2 = read(&rw);
97            assert_eq!(&*r1, "hello");
98            assert_eq!(&*r2, "hello");
99        }
100
101        // Single writer
102        {
103            let mut w = write(&rw);
104            *w = String::from("world");
105        }
106
107        assert_eq!(&*read(&rw), "world");
108    }
109
110    #[test]
111    fn test_channel() {
112        let (tx, rx) = channel();
113
114        tx.send(42).unwrap();
115        assert_eq!(rx.recv().unwrap(), 42);
116    }
117
118    #[test]
119    fn test_arc_mutex() {
120        let data = arc_mutex(0);
121        let data2 = Arc::clone(&data);
122
123        *lock(&data) = 5;
124        assert_eq!(*lock(&data2), 5);
125    }
126}