struct State {
global: Global,
accounts: SlotMap<AId, ARecord>,
}
Expand description
Memory tracker inner, including mutable state
§Module internal documentation
§Data structure
MemoryQuotaTracker
contains mutex-protectedState
.- The
State
contains aSlotMap
of account recordsARecord
. - Each
ARecord
contains aSlotMap
of participant recordsPRecord
.
The handles Account
, WeakAccount
, and Participation
,
each contain a reference (Arc
/Weak
) to the MemoryQuotaTracker
,
and the necessary slotmap keys.
The ARecord
and PRecord
each contain a reference count,
which is used to clean up when all the handles are gone.
The slotmap keys which count for the reference count (ie, strong references)
are stored as refcount::Ref
,
which helps assure correct reference counting.
(Bare ids AId
and PId
are weak references.)
§Data structure lookup
Given a reference to the tracker, and some ids, the macro find_in_tracker!
is used to obtain mutable references to the ARecord
and (if applicable) PRecord
.
§Bookkeeping
We use separate types for quantities of memory in various “states”, rather than working with raw quantities.
The types, and the legitimate transactions, are in bookkeeping
.
§Reentrancy (esp. Drop
and Clone
)
When the handle structs are dropped or cloned, they must manipulate the refcount(s).
So they must take the lock.
Therefore, an Account
and Participation
may not be dropped with the lock held!
Internally, this is actually fairly straightforward: we take handles by reference, and constructors only make them at the last moment on return, so our internal code here, in this module, doesn’t have owned handles.
We also need to worry about reentrantly reentering the tracker code, from user code.
The user supplies a dyn IsParticipant
.
The principal methods are from IsParticipant
,
for which we handle reentrancy in the docs.
But we also implicitly invoke its Drop
impl, which might in turn drop stuff of ours,
such as Account
s and Participation
s, whose Drop
impls need to take our lock.
To make sure this isn’t done reentrantly, we have a special newtype around it,
and defer some of our drops during reclaim.
That’s in drop_reentrancy
and tracker::reclaim::deferred_drop
.
The Debug
impl isn’t of concern, since we don’t call it ourselves.
And we don’t rely on it being Clone
, since it’s in an Arc
.
§Drop bombs
With #[cfg(test)]
, several of our types have “drop bombs”:
they cause a panic if dropped inappropriately.
This is intended to detect bad code paths during testing.
Fields§
§global: Global
Global parts of state
Broken out to allow passing both
&mut Global
and &mut ARecord
/&mut PRecord
to some function(s).
accounts: SlotMap<AId, ARecord>
Accounts
Implementations§
Trait Implementations§
Auto Trait Implementations§
impl Freeze for State
impl !RefUnwindSafe for State
impl Send for State
impl Sync for State
impl Unpin for State
impl !UnwindSafe for State
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more