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