Implement `LWWReg` in terms of `Max`
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
parent
b11826b113
commit
0482757ce9
|
|
@ -13,7 +13,7 @@ mod test;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A join-semilattice.
|
||||
pub trait Semilattice: Default {
|
||||
pub trait Semilattice {
|
||||
/// Join or "merge" two semilattices into one.
|
||||
fn join(self, other: Self) -> Self;
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ pub trait Semilattice: Default {
|
|||
/// Reduce an iterator of semilattice values to its least upper bound.
|
||||
pub fn fold<S>(i: impl IntoIterator<Item = S>) -> S
|
||||
where
|
||||
S: Semilattice,
|
||||
S: Semilattice + Default,
|
||||
{
|
||||
i.into_iter().fold(S::default(), S::join)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +1,41 @@
|
|||
use crate::ord::Max;
|
||||
use crate::Semilattice;
|
||||
|
||||
/// Last-Write-Wins Register.
|
||||
///
|
||||
/// In case of conflict, biased towards larger values.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct LWWReg<T, C> {
|
||||
value: T,
|
||||
clock: C,
|
||||
/// Nb. the order of the tuple types ensures we bias towards the clock before the value.
|
||||
inner: Max<(C, T)>,
|
||||
}
|
||||
|
||||
impl<T: PartialOrd, C: PartialOrd> LWWReg<T, C> {
|
||||
pub fn new(value: T, clock: C) -> Self {
|
||||
Self { value, clock }
|
||||
}
|
||||
|
||||
pub fn set(&mut self, value: T, clock: C) {
|
||||
if clock > self.clock || (clock == self.clock && value > self.value) {
|
||||
self.value = value;
|
||||
self.clock = clock;
|
||||
Self {
|
||||
inner: Max::from((clock, value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, value: T, clock: C) {
|
||||
self.inner.merge(Max::from((clock, value)));
|
||||
}
|
||||
|
||||
pub fn get(&self) -> &T {
|
||||
&self.value
|
||||
&self.inner.get().1
|
||||
}
|
||||
|
||||
pub fn clock(&self) -> &C {
|
||||
&self.clock
|
||||
&self.inner.get().0
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> (T, C) {
|
||||
(self.value, self.clock)
|
||||
let (t, c) = self.inner.into_inner();
|
||||
(c, t)
|
||||
}
|
||||
|
||||
pub fn merge(&mut self, other: Self) {
|
||||
self.set(other.value, other.clock);
|
||||
self.inner.merge(other.inner);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -43,9 +44,10 @@ where
|
|||
T: PartialOrd + Default,
|
||||
C: PartialOrd + Default,
|
||||
{
|
||||
fn join(mut self, other: Self) -> Self {
|
||||
self.merge(other);
|
||||
self
|
||||
fn join(self, other: Self) -> Self {
|
||||
Self {
|
||||
inner: self.inner.join(other.inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,31 @@
|
|||
use std::{cmp, ops};
|
||||
|
||||
use num_traits::Bounded;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Semilattice;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct Max<T>(T);
|
||||
|
||||
impl<T> Max<T> {
|
||||
pub fn get(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd> Max<T> {
|
||||
pub fn merge(&mut self, other: Self) {
|
||||
if other.0 > self.0 {
|
||||
self.0 = other.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: num_traits::SaturatingAdd + num_traits::One> Max<T> {
|
||||
pub fn incr(&mut self) {
|
||||
self.0 = self.0.saturating_add(&T::one());
|
||||
|
|
@ -13,7 +34,7 @@ impl<T: num_traits::SaturatingAdd + num_traits::One> Max<T> {
|
|||
|
||||
impl<T> Default for Max<T>
|
||||
where
|
||||
T: num_traits::bounds::Bounded,
|
||||
T: Bounded,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self(T::min_value())
|
||||
|
|
@ -34,13 +55,23 @@ impl<T> From<T> for Max<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd> Semilattice for Max<T> {
|
||||
fn join(self, other: Self) -> Self {
|
||||
if other.0 > self.0 {
|
||||
other
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
||||
pub struct Min<T>(pub T);
|
||||
|
||||
impl<T> Default for Min<T>
|
||||
where
|
||||
T: num_traits::bounds::Bounded,
|
||||
T: Bounded,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self(T::max_value())
|
||||
|
|
|
|||
Loading…
Reference in New Issue