Skip to main content

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	pub fn is_clone(&self, other: &Self) -> bool {
23		std::sync::Arc::ptr_eq(&self.inner, &other.inner)
24	}
25}
26
27impl<T> Lock<T> {
28	pub fn lock(&self) -> LockGuard<'_, T> {
29		LockGuard::new(&self.inner)
30	}
31
32	pub fn downgrade(&self) -> LockWeak<T> {
33		LockWeak::new(&self.inner)
34	}
35}
36
37#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
38impl<T> Lock<T> {
39	pub fn new(value: T) -> Self {
40		Self {
41			inner: std::rc::Rc::new(std::cell::RefCell::new(value)),
42		}
43	}
44
45	pub fn is_clone(&self, other: &Self) -> bool {
46		std::rc::Rc::ptr_eq(&self.inner, &other.inner)
47	}
48}
49
50impl<T: Default> Default for Lock<T> {
51	fn default() -> Self {
52		Self::new(T::default())
53	}
54}
55
56impl<T> Clone for Lock<T> {
57	fn clone(&self) -> Self {
58		Self {
59			inner: self.inner.clone(),
60		}
61	}
62}
63
64impl<T: fmt::Debug> fmt::Debug for Lock<T> {
65	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66		self.inner.fmt(f)
67	}
68}
69
70pub struct LockGuard<'a, T> {
71	#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
72	inner: std::sync::MutexGuard<'a, T>,
73
74	#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
75	inner: std::cell::RefMut<'a, T>,
76}
77
78#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
79impl<'a, T> LockGuard<'a, T> {
80	fn new(inner: &'a std::sync::Arc<std::sync::Mutex<T>>) -> Self {
81		Self {
82			inner: inner.lock().unwrap(),
83		}
84	}
85}
86
87#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
88impl<'a, T> LockGuard<'a, T> {
89	fn new(inner: &'a std::rc::Rc<std::cell::RefCell<T>>) -> Self {
90		Self {
91			inner: inner.borrow_mut(),
92		}
93	}
94}
95
96impl<T> Deref for LockGuard<'_, T> {
97	type Target = T;
98
99	fn deref(&self) -> &Self::Target {
100		&self.inner
101	}
102}
103
104impl<T> DerefMut for LockGuard<'_, T> {
105	fn deref_mut(&mut self) -> &mut Self::Target {
106		&mut self.inner
107	}
108}
109
110impl<T: fmt::Debug> fmt::Debug for LockGuard<'_, T> {
111	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112		self.inner.fmt(f)
113	}
114}
115
116pub struct LockWeak<T> {
117	#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
118	inner: std::sync::Weak<std::sync::Mutex<T>>,
119
120	#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
121	inner: std::rc::Weak<std::cell::RefCell<T>>,
122}
123
124#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
125impl<T> LockWeak<T> {
126	fn new(inner: &std::sync::Arc<std::sync::Mutex<T>>) -> Self {
127		Self {
128			inner: std::sync::Arc::downgrade(inner),
129		}
130	}
131}
132
133#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
134impl<T> LockWeak<T> {
135	fn new(inner: &std::rc::Rc<std::cell::RefCell<T>>) -> Self {
136		Self {
137			inner: std::rc::Rc::downgrade(inner),
138		}
139	}
140}
141
142impl<T> LockWeak<T> {
143	pub fn upgrade(&self) -> Option<Lock<T>> {
144		Some(Lock {
145			inner: self.inner.upgrade()?,
146		})
147	}
148}
149
150impl<T> Clone for LockWeak<T> {
151	fn clone(&self) -> Self {
152		Self {
153			inner: self.inner.clone(),
154		}
155	}
156}