1 //! Synchronization primitives for Wasmtime.
2 //!
3 //! This is a small set of primitives split between std and no_std with "dummy"
4 //! implementation on no_std. The no_std implementations live in
5 //! `sync_nostd.rs`.
6 
7 use once_cell::sync::OnceCell;
8 use std::ops::{Deref, DerefMut};
9 
10 /// This type is intended to mirror, and one day be implemented by, the
11 /// `std::sync::OnceLock` type. At this time
12 /// `std::sync::OnceLock::get_or_try_init` is not stable so for now this is
13 /// implemented with the `once_cell` crate instead.
14 pub struct OnceLock<T>(OnceCell<T>);
15 
16 impl<T> OnceLock<T> {
17     #[inline]
new() -> OnceLock<T>18     pub const fn new() -> OnceLock<T> {
19         OnceLock(OnceCell::new())
20     }
21 
22     #[inline]
get_or_init(&self, f: impl FnOnce() -> T) -> &T23     pub fn get_or_init(&self, f: impl FnOnce() -> T) -> &T {
24         self.0.get_or_init(f)
25     }
26 
27     #[inline]
get_or_try_init<E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<&T, E>28     pub fn get_or_try_init<E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<&T, E> {
29         self.0.get_or_try_init(f)
30     }
31 }
32 
33 impl<T> Default for OnceLock<T> {
default() -> OnceLock<T>34     fn default() -> OnceLock<T> {
35         OnceLock::new()
36     }
37 }
38 
39 /// Small wrapper around `std::sync::RwLock` which undoes poisoning.
40 #[derive(Debug, Default)]
41 pub struct RwLock<T>(std::sync::RwLock<T>);
42 
43 impl<T> RwLock<T> {
44     #[inline]
new(val: T) -> RwLock<T>45     pub const fn new(val: T) -> RwLock<T> {
46         RwLock(std::sync::RwLock::new(val))
47     }
48 
49     #[inline]
read(&self) -> impl Deref<Target = T> + '_50     pub fn read(&self) -> impl Deref<Target = T> + '_ {
51         self.0.read().unwrap()
52     }
53 
54     #[inline]
write(&self) -> impl DerefMut<Target = T> + '_55     pub fn write(&self) -> impl DerefMut<Target = T> + '_ {
56         self.0.write().unwrap()
57     }
58 }
59