1use crate::lane::LaneError;
26use crate::renderer::error::{RenderError, ResourceError};
27use std::sync::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
28
29pub fn mutex_lock<'a, T: ?Sized>(
35 lock: &'a Mutex<T>,
36 context: &'static str,
37) -> Result<MutexGuard<'a, T>, LaneError> {
38 lock.lock().map_err(|_| LaneError::lock_poisoned(context))
39}
40
41pub fn read_lock<'a, T: ?Sized>(
43 lock: &'a RwLock<T>,
44 context: &'static str,
45) -> Result<RwLockReadGuard<'a, T>, LaneError> {
46 lock.read().map_err(|_| LaneError::lock_poisoned(context))
47}
48
49pub fn write_lock<'a, T: ?Sized>(
51 lock: &'a RwLock<T>,
52 context: &'static str,
53) -> Result<RwLockWriteGuard<'a, T>, LaneError> {
54 lock.write().map_err(|_| LaneError::lock_poisoned(context))
55}
56
57pub fn mutex_lock_render<'a, T: ?Sized>(
64 lock: &'a Mutex<T>,
65 context: &'static str,
66) -> Result<MutexGuard<'a, T>, RenderError> {
67 lock.lock().map_err(|_| {
68 RenderError::ResourceError(ResourceError::BackendError(format!(
69 "{}: lock poisoned",
70 context
71 )))
72 })
73}
74
75pub fn write_lock_render<'a, T: ?Sized>(
77 lock: &'a RwLock<T>,
78 context: &'static str,
79) -> Result<RwLockWriteGuard<'a, T>, RenderError> {
80 lock.write().map_err(|_| {
81 RenderError::ResourceError(ResourceError::BackendError(format!(
82 "{}: lock poisoned",
83 context
84 )))
85 })
86}
87
88pub fn read_lock_render<'a, T: ?Sized>(
90 lock: &'a RwLock<T>,
91 context: &'static str,
92) -> Result<RwLockReadGuard<'a, T>, RenderError> {
93 lock.read().map_err(|_| {
94 RenderError::ResourceError(ResourceError::BackendError(format!(
95 "{}: lock poisoned",
96 context
97 )))
98 })
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use std::sync::Arc;
105
106 #[test]
107 fn mutex_lock_succeeds() {
108 let m = Mutex::new(42);
109 let guard = mutex_lock(&m, "test").unwrap();
110 assert_eq!(*guard, 42);
111 }
112
113 #[test]
114 fn mutex_lock_returns_lane_error_when_poisoned() {
115 let m = Arc::new(Mutex::new(0));
116 let m_clone = Arc::clone(&m);
117 let _ = std::thread::spawn(move || {
118 let _g = m_clone.lock().unwrap();
119 panic!("poison the mutex");
120 })
121 .join();
122 let err = mutex_lock(&m, "poisoned").unwrap_err();
123 assert!(matches!(
124 err,
125 LaneError::LockPoisoned {
126 context: "poisoned"
127 }
128 ));
129 }
130
131 #[test]
132 fn rwlock_read_succeeds() {
133 let l = RwLock::new(7);
134 let g = read_lock(&l, "test").unwrap();
135 assert_eq!(*g, 7);
136 }
137
138 #[test]
139 fn rwlock_write_succeeds() {
140 let l = RwLock::new(0);
141 {
142 let mut g = write_lock(&l, "test").unwrap();
143 *g = 9;
144 }
145 assert_eq!(*l.read().unwrap(), 9);
146 }
147}