pub struct InMemory<C> { /* private fields */ }Expand description
Transient, cell-local storage for state that must not be persisted, such as host resource handles (sockets, subscriptions, scan sessions, …) held across handler invocations.
Unlike State, InMemory never touches the data layer: the wrapped value only lives for as
long as the cell instance is loaded and is lost on restart. It is typically stored in a
static and accessed through InMemory::with.
Wrap the value in an Option and declare it with InMemory::empty when it only becomes
available at runtime, such as a handle returned by a host call.
Implementations§
Source§impl<C> InMemory<C>
impl<C> InMemory<C>
Sourcepub fn with<R>(&self, f: impl FnOnce(&mut C) -> R) -> Result<R>
pub fn with<R>(&self, f: impl FnOnce(&mut C) -> R) -> Result<R>
Runs f with mutable access to the wrapped value.
This covers the common case of reading or updating the value in a single expression. If
you need to interleave the access with control flow in the caller, such as an early
return, a return inside f only exits f itself; use InMemory::try_borrow_mut
or InMemory::try_borrow instead, since the guard they return lives in the caller’s
own scope.
§Errors
Returns an error if with is called re-entrantly, i.e. from within another call to
with/upsert_with/try_borrow/try_borrow_mut on the same InMemory (for example,
from a callback invoked by f).
Sourcepub fn try_borrow(&self) -> Result<Ref<'_, C>>
pub fn try_borrow(&self) -> Result<Ref<'_, C>>
Immutably borrows the wrapped value.
Prefer this over InMemory::with when the access needs to be interleaved with control
flow in the caller, since the returned guard lives in the caller’s own scope rather than
inside a closure.
§Errors
Returns an error if the value is currently mutably borrowed, i.e. from a re-entrant call
to with/upsert_with/try_borrow_mut (for example, from within a callback).
Sourcepub fn try_borrow_mut(&self) -> Result<RefMut<'_, C>>
pub fn try_borrow_mut(&self) -> Result<RefMut<'_, C>>
Mutably borrows the wrapped value.
Prefer this over InMemory::with when the access needs to be interleaved with control
flow in the caller, since the returned guard lives in the caller’s own scope rather than
inside a closure.
§Errors
Returns an error if the value is already borrowed, i.e. from a re-entrant call to
with/upsert_with/try_borrow/try_borrow_mut (for example, from within a callback).
Source§impl<T> InMemory<Option<T>>
impl<T> InMemory<Option<T>>
Sourcepub const fn empty() -> Self
pub const fn empty() -> Self
Declares a InMemory that starts out without a value.
Use this for a value that can only be built at runtime, such as a handle returned by a
host call. The Option is part of the stored type, so InMemory::with hands the
closure an &mut Option<T> and the caller deals with exactly one level of optionality:
static SCAN: InMemory<Option<ScanHandle>> = InMemory::empty();
SCAN.with(|slot| *slot = Some(scan))?;
if let Some(scan) = SCAN.with(Option::take)? {
scan.stop()?;
}When T implements Default, InMemory::upsert_with hands the closure an &mut T
instead, inserting the default value first.
Source§impl<T> InMemory<Option<T>>where
T: Default,
impl<T> InMemory<Option<T>>where
T: Default,
Sourcepub fn upsert_with<R>(&self, f: impl FnOnce(&mut T) -> R) -> Result<R>
pub fn upsert_with<R>(&self, f: impl FnOnce(&mut T) -> R) -> Result<R>
Runs f with mutable access to the wrapped value, inserting T::default() first if there
is no value yet.
This mirrors the upsert family on State for a value that is never persisted. Since the
insert guarantees a value, f receives an &mut T and its result is not wrapped in an
Option, which makes this the more direct way to build a value up field by field across
several invocations:
static SESSION: InMemory<Option<Session>> = InMemory::empty();
SESSION.upsert_with(|session| session.scan = Some(scan))?;§Errors
Returns an error if upsert_with is called re-entrantly, i.e. from within another call to
with/upsert_with/try_borrow/try_borrow_mut on the same InMemory (for example,
from a callback invoked by f).