use crate::control::automaton::txn::{Closed, InAcked, InBegin, Tap, Txn};
use crate::control::types::{
AtMostOnceCommit, Generation, IncreasingGen, Lane, NoCrossLaneAliasing, One,
};
pub(crate) struct DistributedTopologyInv;
impl NoCrossLaneAliasing for DistributedTopologyInv {}
impl AtMostOnceCommit for DistributedTopologyInv {}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct TopologyIntent {
pub(crate) src_rv: crate::control::types::RendezvousId,
pub(crate) dst_rv: crate::control::types::RendezvousId,
pub(crate) sid: u32,
pub(crate) old_gen: Generation,
pub(crate) new_gen: Generation,
pub(crate) seq_tx: u32,
pub(crate) seq_rx: u32,
pub(crate) src_lane: Lane,
pub(crate) dst_lane: Lane,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct TopologyAck {
pub(crate) src_rv: crate::control::types::RendezvousId,
pub(crate) dst_rv: crate::control::types::RendezvousId,
pub(crate) sid: u32,
pub(crate) new_gen: Generation,
pub(crate) src_lane: Lane,
pub(crate) new_lane: Lane,
pub(crate) seq_tx: u32,
pub(crate) seq_rx: u32,
}
impl TopologyAck {
pub(crate) fn from_intent(intent: &TopologyIntent) -> Self {
Self {
src_rv: intent.src_rv,
dst_rv: intent.dst_rv,
sid: intent.sid,
new_gen: intent.new_gen,
src_lane: intent.src_lane,
new_lane: intent.dst_lane,
seq_tx: intent.seq_tx,
seq_rx: intent.seq_rx,
}
}
}
pub(crate) struct DistributedTopology;
impl DistributedTopology {
pub(crate) fn begin(
intent: TopologyIntent,
tap: &mut impl Tap,
) -> (InBegin<DistributedTopologyInv, One>, TopologyIntent) {
let txn: Txn<DistributedTopologyInv, IncreasingGen, One> =
unsafe { Txn::new(intent.src_lane, intent.old_gen) };
let in_begin = txn.begin(tap);
(in_begin, intent)
}
pub(crate) fn acknowledge(
in_begin: InBegin<DistributedTopologyInv, One>,
tap: &mut impl Tap,
) -> InAcked<DistributedTopologyInv, One> {
in_begin.ack(tap)
}
pub(crate) fn topology_commit(
in_acked: InAcked<DistributedTopologyInv, One>,
tap: &mut impl Tap,
) -> Closed<DistributedTopologyInv> {
in_acked.commit(tap)
}
}
#[cfg(test)]
mod tests {
use super::super::txn::NoopTap;
use super::*;
use crate::control::types::RendezvousId;
#[test]
fn distributed_topology_typestate_begin_ack_commit_path_closes() {
let mut tap = NoopTap;
let (in_begin, intent) = DistributedTopology::begin(
TopologyIntent {
src_rv: RendezvousId::new(1),
dst_rv: RendezvousId::new(2),
sid: 42,
old_gen: Generation::new(10),
new_gen: Generation::new(11),
seq_tx: 0,
seq_rx: 0,
src_lane: Lane::new(1),
dst_lane: Lane::new(2),
},
&mut tap,
);
assert_eq!(intent.sid, 42);
assert_eq!(intent.src_lane, Lane::new(1));
assert_eq!(intent.dst_lane, Lane::new(2));
assert_eq!(intent.old_gen, Generation::new(10));
assert_eq!(intent.new_gen, Generation::new(11));
let in_acked = DistributedTopology::acknowledge(in_begin, &mut tap);
DistributedTopology::topology_commit(in_acked, &mut tap);
}
}