pub struct EngineCell<T: ?Sized> { /* private fields */ }Expand description
A Sync wrapper holding a single value of type T.
§Storage convention
This type aligns with the rest of the engine’s static mut
convention used in core::reactive::hook::impl. The companion
storage helpers try_get / try_get_mut / get / get_mut
return &'static mut T and rely on the caller to honour the
single-writer contract. The engine is compiled for
wasm32-unknown-unknown which is single-threaded by contract,
so overlapping borrows violate the caller contract rather than
being trapped at runtime the way RefCell would.
RefCell is intentionally not used as the storage backend:
its runtime aliasing panic is unreachable in practice under
wasm’s single-threaded model and adds code size and a redundant
safety net that the rest of the codebase does not provide.
§?Sized bound and trait-object storage
The T: ?Sized bound is what lets the engine alias
Rc<EngineCell<dyn Trait>> directly (see ComponentRc,
SceneRc, TickHandlerRc in their respective type.rs). The
trait-object fat pointer is stored in-place inside the
UnsafeCell<T>; get_mut -> &'static mut dyn Trait lets
callers dispatch without an intermediate Box.
§When to choose this vs MaybeEngineCell
The cell has no notion of “uninitialized” - use MaybeEngineCell
if the value may legitimately be absent (the typical case for
“global installed at mount, torn down at unmount” singletons).
For always-present values this is a zero-overhead wrapper around
UnsafeCell<T>.
§Field access rule
The inner field is reached through the hand-written
get_inner / set_inner accessors declared in cell/impl.rs.
All read sites in this module call get_inner().get() and write
sites use set_inner(UnsafeCell::new(value)) rather than touching
the field directly. Struct literals Self { inner: ... } are
permitted only inside the new constructor and the Default
impl, per the engine’s “exceptions to no-direct-field-access”
convention.
§Note on #[derive(Data)]
Lombok’s Data derive is intentionally not applied here:
the derive requires T: Sized, which would defeat the ?Sized
bound above and break the engine’s Rc<EngineCell<dyn Trait>>
aliases. The accessor pair is hand-written in cell/impl.rs
with the same Lombok-style contract.
Implementations§
Source§impl<T: ?Sized> EngineCell<T>
Accessor implementations for EngineCell.
impl<T: ?Sized> EngineCell<T>
Accessor implementations for EngineCell.
Sourcepub fn get_inner(&self) -> &UnsafeCell<T>
pub fn get_inner(&self) -> &UnsafeCell<T>
Returns a shared reference to the backing UnsafeCell<T>.
§Returns
&UnsafeCell<T>- The backing storage of the cell, borrowed for the lifetime of the cell.
Source§impl<T: ?Sized> EngineCell<T>
Constructor + read accessors for EngineCell.
impl<T: ?Sized> EngineCell<T>
Constructor + read accessors for EngineCell.
Sourcepub fn new(value: T) -> Selfwhere
T: Sized,
pub fn new(value: T) -> Selfwhere
T: Sized,
Creates a new cell with the given initial value.
Construction is the one place where direct field initialisation
is permitted (see field-access rule in struct.rs); all other
sites must go through the accessors.
Sourcepub fn get_mut(&self) -> &'static mut T
pub fn get_mut(&self) -> &'static mut T
Returns a mutable reference to the contained value.
§Safety
The borrow MUST be exclusive - no other get, get_mut,
try_get, or try_get_mut on the same cell may be alive when
the returned reference is used. Two concurrent mutable borrows on
a wasm single-threaded runtime are well-defined in practice only
because wasm has no data-race detection; the &'static mut
return type tells the borrow checker you promise exclusivity.
Reads via the get_inner accessor; the resulting
&UnsafeCell<T> is then turned into a raw pointer by
UnsafeCell::get() so we can hand the caller the
&'static mut T the rest of the engine expects.
Sourcepub fn get(&self) -> &'static T
pub fn get(&self) -> &'static T
Returns a shared reference to the contained value.
§Safety
The lifetime of &'static T extends beyond what the borrow
checker can prove. Callers MUST NOT use this while a mutable
borrow on the same cell is alive. Use Self::get_mut
exclusively for write access.
Reads via the get_inner accessor + UnsafeCell::get.
Trait Implementations§
Source§impl<T: Default> Default for EngineCell<T>
Default impl for EngineCell.
impl<T: Default> Default for EngineCell<T>
Default impl for EngineCell.
Only available when T: Default + Sized. The ?Sized bound on
the cell prevents adding Default blanket-style because trait
Default cannot be implemented for unsized types.
impl<T: ?Sized> Sync for EngineCell<T>
Marker that EngineCell<T> is safe to share across the wasm main
thread under single-threaded access.