web_async/
lock.rs

1use std::fmt;
2use std::ops::{Deref, DerefMut};
3
4// It's a cosmetic wrapper around Arc<Mutex<T>> on native platforms.
5// On WASM, it uses Rc<RefCell<T>> instead.
6pub struct Lock<T> {
7	#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
8	inner: std::sync::Arc<std::sync::Mutex<T>>,
9
10	#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
11	inner: std::rc::Rc<std::cell::RefCell<T>>,
12}
13
14#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
15impl<T> Lock<T> {
16	pub fn new(value: T) -> Self {
17		Self {
18			inner: std::sync::Arc::new(std::sync::Mutex::new(value)),
19		}
20	}
21}
22
23impl<T> Lock<T> {
24	pub fn lock(&self) -> LockGuard<T> {
25		LockGuard::new(&self.inner)
26	}
27
28	pub fn downgrade(&self) -> LockWeak<T> {
29		LockWeak::new(&self.inner)
30	}
31}
32
33#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
34impl<T> Lock<T> {
35	pub fn new(value: T) -> Self {
36		Self {
37			inner: std::rc::Rc::new(std::cell::RefCell::new(value)),
38		}
39	}
40}
41
42impl<T: Default> Default for Lock<T> {
43	fn default() -> Self {
44		Self::new(T::default())
45	}
46}
47
48impl<T> Clone for Lock<T> {
49	fn clone(&self) -> Self {
50		Self {
51			inner: self.inner.clone(),
52		}
53	}
54}
55
56pub struct LockGuard<'a, T> {
57	#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
58	inner: std::sync::MutexGuard<'a, T>,
59
60	#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
61	inner: std::cell::RefMut<'a, T>,
62}
63
64#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
65impl<'a, T> LockGuard<'a, T> {
66	fn new(inner: &'a std::sync::Arc<std::sync::Mutex<T>>) -> Self {
67		Self {
68			inner: inner.lock().unwrap(),
69		}
70	}
71}
72
73#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
74impl<'a, T> LockGuard<'a, T> {
75	fn new(inner: &'a std::rc::Rc<std::cell::RefCell<T>>) -> Self {
76		Self {
77			inner: inner.borrow_mut(),
78		}
79	}
80}
81
82impl<T> Deref for LockGuard<'_, T> {
83	type Target = T;
84
85	fn deref(&self) -> &Self::Target {
86		&self.inner
87	}
88}
89
90impl<T> DerefMut for LockGuard<'_, T> {
91	fn deref_mut(&mut self) -> &mut Self::Target {
92		&mut self.inner
93	}
94}
95
96impl<T: fmt::Debug> fmt::Debug for LockGuard<'_, T> {
97	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98		self.inner.fmt(f)
99	}
100}
101
102pub struct LockWeak<T> {
103	#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
104	inner: std::sync::Weak<std::sync::Mutex<T>>,
105
106	#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
107	inner: std::rc::Weak<std::cell::RefCell<T>>,
108}
109
110#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
111impl<T> LockWeak<T> {
112	fn new(inner: &std::sync::Arc<std::sync::Mutex<T>>) -> Self {
113		Self {
114			inner: std::sync::Arc::downgrade(inner),
115		}
116	}
117}
118
119#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
120impl<T> LockWeak<T> {
121	fn new(inner: &std::rc::Rc<std::cell::RefCell<T>>) -> Self {
122		Self {
123			inner: std::rc::Rc::downgrade(inner),
124		}
125	}
126}
127
128impl<T> LockWeak<T> {
129	pub fn upgrade(&self) -> Option<Lock<T>> {
130		Some(Lock {
131			inner: self.inner.upgrade()?,
132		})
133	}
134}
135
136impl<T> Clone for LockWeak<T> {
137	fn clone(&self) -> Self {
138		Self {
139			inner: self.inner.clone(),
140		}
141	}
142}