pub struct Slot<Parent, Child> {
pub read: fn(&Parent) -> Option<&Child>,
pub write: fn(Option<&Parent>, Child) -> Parent,
}Expand description
Where a child’s durable record lives inside its parent’s.
A parent and a child sharing one store would collide on the metadata: each set would
overwrite the other’s. A Slot says which part of the parent’s record belongs to the child, so
the child’s set becomes a read-modify-write of the parent’s — one record, one write, which
is what keeps durable-before-visible meaning what it says. Two writes could be interrupted
between them; one cannot.
Both halves are fn pointers rather than closures, for the same reason the composition mappers
are: a slot must not capture. It names a fixed place in a type, and a slot that could close over
state would be a different place on different calls.
write takes the parent’s record as an Option because the child may write first: nothing is
stored until something is, and the child’s own Init is often the first event of the run. The
implementation is then “start from the parent’s default, put the child’s part in it”.
#[derive(Clone, Default, PartialEq, Debug)]
struct Parent { mine: u64, childs: Option<u32> }
const CHILD: Slot<Parent, u32> = Slot {
read: |p| p.childs.as_ref(),
write: |p, c| Parent { childs: Some(c), ..p.cloned().unwrap_or_default() },
};
assert_eq!((CHILD.read)(&Parent { mine: 1, childs: Some(7) }), Some(&7));
assert_eq!((CHILD.write)(None, 7), Parent { mine: 0, childs: Some(7) });§The sequence half is SeqSlot
A Slot scopes the metadata only, so Cx::with_durable_child_consuming hands the child a
store whose Entry is uninhabited: such a child cannot append, and the signature says so rather
than a comment. That is still the right default, and most durable children want nothing else.
A child that appends is composed through SeqSlot as well, with
Cx::with_durable_child. This paragraph used to say the shape
such a thing would take and that nothing needed it — “building it now would be the framework
before its second consumer”. The second consumer arrived: the fail-recovery total-order
broadcast keeps a durable record of its own and composes
logged_uniform_reliable_broadcast, which is the one protocol here that appends. What was
built is what that paragraph described, unchanged.
Fields§
§read: fn(&Parent) -> Option<&Child>The child’s record, as it sits inside the parent’s.
write: fn(Option<&Parent>, Child) -> ParentThe parent’s record with the child’s part replaced.