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

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

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.

Drop the first of the two copies.

Defaults to calling Self::drop.

Drop the second of the two copies.

Defaults to calling Self::drop.

Implementors