Trait left_right::Absorb
source · [−]pub trait Absorb<O> {
fn absorb_first(&mut self, operation: &mut O, other: &Self);
fn sync_with(&mut self, first: &Self);
fn absorb_second(&mut self, operation: O, other: &Self) { ... }
fn drop_first(self: Box<Self>) { ... }
fn drop_second(self: Box<Self>) { ... }
}
Expand description
Types that can incorporate operations of type O
.
This trait allows left-right
to keep the two copies of the underlying data structure (see the
crate-level documentation) the same over time. Each write operation to the data
structure is logged as an operation of type O
in an operational log (oplog), and is applied
once to each copy of the data.
Implementations should ensure that the absorbption of each O
is deterministic. That is, if
two instances of the implementing type are initially equal, and then absorb the same O
,
they should remain equal afterwards. If this is not the case, the two copies will drift apart
over time, and hold different values.
The trait provides separate methods for the first and second absorption of each O
. For many
implementations, these will be the same (which is why absorb_second
defaults to calling
absorb_first
), but not all. In particular, some implementations may need to modify the O
to
ensure deterministic results when it is applied to the second copy. Or, they may need to
ensure that removed values in the data structure are only dropped when they are removed from
both copies, in case they alias the backing data to save memory.
For the same reason, Absorb
allows implementors to define drop_first
, which is used to drop
the first of the two copies. In this case, de-duplicating implementations may need to forget
values rather than drop them so that they are not dropped twice when the second copy is
dropped.
Required Methods
fn absorb_first(&mut self, operation: &mut O, other: &Self)
fn absorb_first(&mut self, operation: &mut O, other: &Self)
Apply O
to the first of the two copies.
other
is a reference to the other copy of the data, which has seen all operations up
until the previous call to WriteHandle::publish
. That is, other
is one “publish
cycle” behind.
Sync the data from first
into self
.
To improve initialization performance, before the first call to publish
changes aren’t
added to the internal oplog, but applied to the first copy directly using absorb_second
.
The first publish
then calls sync_with
instead of absorb_second
.
sync_with
should ensure that self
’s state exactly matches that of first
after it
returns. Be particularly mindful of non-deterministic implementations of traits that are
often assumed to be deterministic (like Eq
and Hash
), and of “hidden states” that
subtly affect results like the RandomState
of a HashMap
which can change iteration
order.
Provided Methods
fn absorb_second(&mut self, operation: O, other: &Self)
fn absorb_second(&mut self, operation: O, other: &Self)
Apply O
to the second of the two copies.
other
is a reference to the other copy of the data, which has seen all operations up to
the call to WriteHandle::publish
that initially exposed this O
. That is, other
is
one “publish cycle” ahead.
Note that this method should modify the underlying data in exactly the same way as
O
modified other
, otherwise the two copies will drift apart. Be particularly mindful of
non-deterministic implementations of traits that are often assumed to be deterministic
(like Eq
and Hash
), and of “hidden states” that subtly affect results like the
RandomState
of a HashMap
which can change iteration order.
Defaults to calling absorb_first
.
fn drop_first(self: Box<Self>)
fn drop_first(self: Box<Self>)
Drop the first of the two copies.
Defaults to calling Self::drop
.
fn drop_second(self: Box<Self>)
fn drop_second(self: Box<Self>)
Drop the second of the two copies.
Defaults to calling Self::drop
.