181a89169SAlex Crichton //! Synchronization primitives for Wasmtime.
281a89169SAlex Crichton //!
381a89169SAlex Crichton //! This is a small set of primitives split between std and no_std with "dummy"
481a89169SAlex Crichton //! implementation on no_std. The no_std implementations live in
581a89169SAlex Crichton //! `sync_nostd.rs`.
681a89169SAlex Crichton 
781a89169SAlex Crichton use once_cell::sync::OnceCell;
881a89169SAlex Crichton use std::ops::{Deref, DerefMut};
981a89169SAlex Crichton 
1081a89169SAlex Crichton /// This type is intended to mirror, and one day be implemented by, the
1181a89169SAlex Crichton /// `std::sync::OnceLock` type. At this time
1281a89169SAlex Crichton /// `std::sync::OnceLock::get_or_try_init` is not stable so for now this is
1381a89169SAlex Crichton /// implemented with the `once_cell` crate instead.
1481a89169SAlex Crichton pub struct OnceLock<T>(OnceCell<T>);
1581a89169SAlex Crichton 
1681a89169SAlex Crichton impl<T> OnceLock<T> {
1781a89169SAlex Crichton     #[inline]
new() -> OnceLock<T>1881a89169SAlex Crichton     pub const fn new() -> OnceLock<T> {
1981a89169SAlex Crichton         OnceLock(OnceCell::new())
2081a89169SAlex Crichton     }
2181a89169SAlex Crichton 
2281a89169SAlex Crichton     #[inline]
get_or_init(&self, f: impl FnOnce() -> T) -> &T2381a89169SAlex Crichton     pub fn get_or_init(&self, f: impl FnOnce() -> T) -> &T {
2481a89169SAlex Crichton         self.0.get_or_init(f)
2581a89169SAlex Crichton     }
2681a89169SAlex Crichton 
2781a89169SAlex Crichton     #[inline]
get_or_try_init<E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<&T, E>2881a89169SAlex Crichton     pub fn get_or_try_init<E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<&T, E> {
2981a89169SAlex Crichton         self.0.get_or_try_init(f)
3081a89169SAlex Crichton     }
3181a89169SAlex Crichton }
3281a89169SAlex Crichton 
33*e60b6e62SAlex Crichton impl<T> Default for OnceLock<T> {
default() -> OnceLock<T>34*e60b6e62SAlex Crichton     fn default() -> OnceLock<T> {
35*e60b6e62SAlex Crichton         OnceLock::new()
36*e60b6e62SAlex Crichton     }
37*e60b6e62SAlex Crichton }
38*e60b6e62SAlex Crichton 
3981a89169SAlex Crichton /// Small wrapper around `std::sync::RwLock` which undoes poisoning.
4081a89169SAlex Crichton #[derive(Debug, Default)]
4181a89169SAlex Crichton pub struct RwLock<T>(std::sync::RwLock<T>);
4281a89169SAlex Crichton 
4381a89169SAlex Crichton impl<T> RwLock<T> {
4481a89169SAlex Crichton     #[inline]
new(val: T) -> RwLock<T>4581a89169SAlex Crichton     pub const fn new(val: T) -> RwLock<T> {
4681a89169SAlex Crichton         RwLock(std::sync::RwLock::new(val))
4781a89169SAlex Crichton     }
4881a89169SAlex Crichton 
4981a89169SAlex Crichton     #[inline]
read(&self) -> impl Deref<Target = T> + '_5081a89169SAlex Crichton     pub fn read(&self) -> impl Deref<Target = T> + '_ {
5181a89169SAlex Crichton         self.0.read().unwrap()
5281a89169SAlex Crichton     }
5381a89169SAlex Crichton 
5481a89169SAlex Crichton     #[inline]
write(&self) -> impl DerefMut<Target = T> + '_5581a89169SAlex Crichton     pub fn write(&self) -> impl DerefMut<Target = T> + '_ {
5681a89169SAlex Crichton         self.0.write().unwrap()
5781a89169SAlex Crichton     }
5881a89169SAlex Crichton }
59