use crate::{ error, references::{GenerationalRef, GenerationalRefMut}, AnyStorage, MemoryLocation, MemoryLocationInner, Storage, }; use std::cell::{Ref, RefCell, RefMut}; /// A unsync storage. This is the default storage type. #[derive(Default)] pub struct UnsyncStorage(RefCell>>); impl Storage for UnsyncStorage { type Ref = GenerationalRef>; type Mut = GenerationalRefMut>; fn try_read( &'static self, #[cfg(any(debug_assertions, feature = "debug_ownership"))] at: crate::GenerationalRefBorrowInfo, ) -> Result, error::BorrowError> { let borrow = self.0.try_borrow(); #[cfg(any(debug_assertions, feature = "debug_ownership"))] let borrow = borrow.map_err(|_| at.borrowed_from.borrow_error())?; #[cfg(not(any(debug_assertions, feature = "debug_ownership")))] let borrow = borrow.map_err(|_| { error::BorrowError::AlreadyBorrowedMut(error::AlreadyBorrowedMutError {}) })?; Ref::filter_map(borrow, |any| any.as_ref()?.downcast_ref()) .map_err(|_| { error::BorrowError::Dropped(error::ValueDroppedError { #[cfg(any(debug_assertions, feature = "debug_ownership"))] created_at: at.created_at, }) }) .map(|guard| { GenerationalRef::new( guard, #[cfg(any(debug_assertions, feature = "debug_ownership"))] at, ) }) } fn try_write( &'static self, #[cfg(any(debug_assertions, feature = "debug_ownership"))] at: crate::GenerationalRefMutBorrowInfo, ) -> Result, error::BorrowMutError> { let borrow = self.0.try_borrow_mut(); #[cfg(any(debug_assertions, feature = "debug_ownership"))] let borrow = borrow.map_err(|_| at.borrowed_from.borrow_mut_error())?; #[cfg(not(any(debug_assertions, feature = "debug_ownership")))] let borrow = borrow .map_err(|_| error::BorrowMutError::AlreadyBorrowed(error::AlreadyBorrowedError {}))?; RefMut::filter_map(borrow, |any| any.as_mut()?.downcast_mut()) .map_err(|_| { error::BorrowMutError::Dropped(error::ValueDroppedError { #[cfg(any(debug_assertions, feature = "debug_ownership"))] created_at: at.created_at, }) }) .map(|guard| { GenerationalRefMut::new( guard, #[cfg(any(debug_assertions, feature = "debug_ownership"))] at, ) }) } fn set(&self, value: T) { *self.0.borrow_mut() = Some(Box::new(value)); } fn try_map( _self: Self::Ref, f: impl FnOnce(&I) -> Option<&U>, ) -> Option> { let GenerationalRef { inner, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow, .. } = _self; Ref::filter_map(inner, f).ok().map(|inner| GenerationalRef { inner, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow, }) } fn try_map_mut( mut_ref: Self::Mut, f: impl FnOnce(&mut I) -> Option<&mut U>, ) -> Option> { let GenerationalRefMut { inner, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow, .. } = mut_ref; RefMut::filter_map(inner, f) .ok() .map(|inner| GenerationalRefMut { inner, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: crate::GenerationalRefMutBorrowInfo { borrowed_from: borrow.borrowed_from, created_at: borrow.created_at, }, }) } } thread_local! { static UNSYNC_RUNTIME: RefCell>> = RefCell::new(Vec::new()); } impl AnyStorage for UnsyncStorage { fn data_ptr(&self) -> *const () { self.0.as_ptr() as *const () } fn take(&self) -> bool { self.0.borrow_mut().take().is_some() } fn claim() -> MemoryLocation { UNSYNC_RUNTIME.with(|runtime| { if let Some(location) = runtime.borrow_mut().pop() { location } else { let data: &'static MemoryLocationInner = &*Box::leak(Box::new(MemoryLocationInner { data: Self::default(), #[cfg(any(debug_assertions, feature = "check_generation"))] generation: 0.into(), #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: Default::default(), })); MemoryLocation(data) } }) } fn recycle(location: &MemoryLocation) { location.drop(); UNSYNC_RUNTIME.with(|runtime| runtime.borrow_mut().push(*location)); } }