todc-utils
Utilities for building and testing distributed algorithms.
Examples
Consider the following sequential specification for a register containing
u32 values.
use Specification;
use ;
;
Using the Action::Call and Action::Response types, we can model read
and write operations as follows:
- The call of a read operation is modeled by
Call(Read(None))and a response containing the valuexis modeled byResponse(Read(Some(x))). We are use anOptionbecause the value being read cannot be known until the register responds. - Similarily, the call of a write operation with the value
yis modeled byCall(Write(y))and the response is modeled byResponse(Write(y)).
Next, we can define a linearizability for this specification, and check some histories.
use ;
type RegisterChecker = ;
// A history of sequantial operations is always linearizable.
// PO |------| Write(0)
// P1 |------| Read(Some(0))
let history = from_actions;
assert!;
// Concurrent operations might not be linearized
// in the order in which they are called.
// PO |---------------| Write(0)
// P1 |--------------| Write(1)
// P2 |---| Read(Some(1))
// P3 |---| Read(Some(0))
let history = from_actions;
assert!;
// A sequentially consistent history is **not**
// necessarily linearizable.
// PO |---| Write(0)
// P1 |---| Write(1)
// P2 |---| Read(Some(1))
// P3 |---| Read(Some(0))
let history = from_actions;
assert!;
For examples of using WGLChecker to check the linearizability of more
complex histories, see
todc-mem/tests/snapshot/common.rs
or
todc-utils/tests/linearizability/etcd.rs.