document remaining items in generational box

This commit is contained in:
Evan Almloff 2023-11-07 13:19:26 -06:00
parent b3c5158524
commit c1bfe9514f

View file

@ -259,6 +259,7 @@ impl<T, S: Copy> Clone for GenerationalBox<T, S> {
}
}
/// A unsync storage. This is the default storage type.
#[derive(Clone, Copy)]
pub struct UnsyncStorage(&'static RefCell<Option<Box<dyn std::any::Any>>>);
@ -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<Option<Box<dyn std::any::Any + Send + Sync>>>);
@ -277,11 +279,15 @@ impl Default for SyncStorage {
}
}
/// A trait for types that can be mapped.
pub trait Mappable<T>: Deref<Target = T> {
/// The type after the mapping.
type Mapped<U: 'static>: Mappable<U> + Deref<Target = U>;
/// Map the value.
fn map<U: 'static>(_self: Self, f: impl FnOnce(&T) -> &U) -> Self::Mapped<U>;
/// Try to map the value.
fn try_map<U: 'static>(
_self: Self,
f: impl FnOnce(&T) -> Option<&U>,
@ -318,11 +324,15 @@ impl<T> Mappable<T> for MappedRwLockReadGuard<'static, T> {
}
}
/// A trait for types that can be mapped mutably.
pub trait MappableMut<T>: DerefMut<Target = T> {
/// The type after the mapping.
type Mapped<U: 'static>: MappableMut<U> + DerefMut<Target = U>;
/// Map the value.
fn map<U: 'static>(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped<U>;
/// Try to map the value.
fn try_map<U: 'static>(
_self: Self,
f: impl FnOnce(&mut T) -> Option<&mut U>,
@ -340,7 +350,7 @@ impl<T> MappableMut<T> for RefMut<'static, T> {
_self: Self,
f: impl FnOnce(&mut T) -> Option<&mut U>,
) -> Option<Self::Mapped<U>> {
RefMut::try_map(_self, f)
RefMut::filter_map(_self, f).ok()
}
}
@ -359,49 +369,45 @@ impl<T> MappableMut<T> for MappedRwLockWriteGuard<'static, T> {
}
}
/// A trait for a storage backing type. (RefCell, RwLock, etc.)
pub trait Storage<Data>: Copy + AnyStorage + 'static {
/// The reference this storage type returns.
type Ref: Mappable<Data> + Deref<Target = Data>;
/// The mutable reference this storage type returns.
type Mut: MappableMut<Data> + DerefMut<Target = Data>;
/// Try to read the value. Returns None if the value is no longer valid.
fn try_read(&self) -> Option<Self::Ref>;
/// 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<Self::Mut>;
/// 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<Self>);
// {
// 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<Self>;
// 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<Self> {
@ -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<S = UnsyncStorage> {
pub struct MemoryLocation<S = UnsyncStorage> {
data: S,
#[cfg(any(debug_assertions, feature = "check_generation"))]
generation: &'static AtomicU32,