From c1bfe9514f42cfd7dd6335100a50bb5859fc1108 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 7 Nov 2023 13:19:26 -0600 Subject: [PATCH] document remaining items in generational box --- packages/generational-box/src/lib.rs | 49 ++++++++++++++++------------ 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/packages/generational-box/src/lib.rs b/packages/generational-box/src/lib.rs index 89844f713..692af76b0 100644 --- a/packages/generational-box/src/lib.rs +++ b/packages/generational-box/src/lib.rs @@ -259,6 +259,7 @@ impl Clone for GenerationalBox { } } +/// A unsync storage. This is the default storage type. #[derive(Clone, Copy)] pub struct UnsyncStorage(&'static RefCell>>); @@ -268,6 +269,7 @@ impl Default for UnsyncStorage { } } +/// A thread safe storage. This is slower than the unsync storage, but allows you to share the value between threads. #[derive(Clone, Copy)] pub struct SyncStorage(&'static RwLock>>); @@ -277,11 +279,15 @@ impl Default for SyncStorage { } } +/// A trait for types that can be mapped. pub trait Mappable: Deref { + /// The type after the mapping. type Mapped: Mappable + Deref; + /// Map the value. fn map(_self: Self, f: impl FnOnce(&T) -> &U) -> Self::Mapped; + /// Try to map the value. fn try_map( _self: Self, f: impl FnOnce(&T) -> Option<&U>, @@ -318,11 +324,15 @@ impl Mappable for MappedRwLockReadGuard<'static, T> { } } +/// A trait for types that can be mapped mutably. pub trait MappableMut: DerefMut { + /// The type after the mapping. type Mapped: MappableMut + DerefMut; + /// Map the value. fn map(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped; + /// Try to map the value. fn try_map( _self: Self, f: impl FnOnce(&mut T) -> Option<&mut U>, @@ -340,7 +350,7 @@ impl MappableMut for RefMut<'static, T> { _self: Self, f: impl FnOnce(&mut T) -> Option<&mut U>, ) -> Option> { - RefMut::try_map(_self, f) + RefMut::filter_map(_self, f).ok() } } @@ -359,49 +369,45 @@ impl MappableMut for MappedRwLockWriteGuard<'static, T> { } } +/// A trait for a storage backing type. (RefCell, RwLock, etc.) pub trait Storage: Copy + AnyStorage + 'static { + /// The reference this storage type returns. type Ref: Mappable + Deref; + /// The mutable reference this storage type returns. type Mut: MappableMut + DerefMut; + /// Try to read the value. Returns None if the value is no longer valid. fn try_read(&self) -> Option; + /// Read the value. Panics if the value is no longer valid. fn read(&self) -> Self::Ref { self.try_read() .expect("generational box has been invalidated or the type has changed") } + /// Try to write the value. Returns None if the value is no longer valid. fn try_write(&self) -> Option; + /// Write the value. Panics if the value is no longer valid. fn write(&self) -> Self::Mut { self.try_write() .expect("generational box has been invalidated or the type has changed") } + /// Set the value. Panics if the value is no longer valid. fn set(&self, value: Data); } +/// A trait for any storage backing type. pub trait AnyStorage: Default { + /// Get the data pointer. No guarantees are made about the data pointer. It should only be used for debugging. fn data_ptr(&self) -> *const (); + /// Take the value out of the storage. This will return true if the value was taken. fn take(&self) -> bool; + /// Recycle a memory location. This will drop the memory location and return it to the runtime. fn recycle(location: &MemoryLocation); - // { - // location.drop(); - // self.recycled.lock().push(location); - // } + /// Claim a new memory location. This will either create a new memory location or recycle an old one. fn claim() -> MemoryLocation; - // where - // S: Default, - // { - // if let Some(location) = self.recycled.lock().pop() { - // location - // } else { - // MemoryLocation { - // data: Default::default(), - // #[cfg(any(debug_assertions, feature = "check_generation"))] - // generation: Box::leak(Box::new(Default::default())), - // } - // } - // } /// Create a new owner. The owner will be responsible for dropping all of the generational boxes that it creates. fn owner() -> Owner { @@ -450,7 +456,7 @@ impl AnyStorage for UnsyncStorage { MemoryLocation { data: UnsyncStorage(Box::leak(Box::new(RefCell::new(None)))), #[cfg(any(debug_assertions, feature = "check_generation"))] - generation: Box::leak(Box::new(Default::default())), + generation: Box::leak(Box::default()), } } }) @@ -498,7 +504,7 @@ impl AnyStorage for SyncStorage { MemoryLocation { data: SyncStorage(Box::leak(Box::new(RwLock::new(None)))), #[cfg(any(debug_assertions, feature = "check_generation"))] - generation: Box::leak(Box::new(Default::default())), + generation: Box::leak(Box::default()), } } @@ -508,8 +514,9 @@ impl AnyStorage for SyncStorage { } } +/// A memory location. This is the core type that is used to store values. #[derive(Clone, Copy)] -struct MemoryLocation { +pub struct MemoryLocation { data: S, #[cfg(any(debug_assertions, feature = "check_generation"))] generation: &'static AtomicU32,