SequentialConsistencyTester

Struct SequentialConsistencyTester 

Source
pub struct SequentialConsistencyTester<ThreadId, RefObj: SequentialSpec> { /* private fields */ }
Expand description

This tester captures a potentially concurrent history of operations and validates that it adheres to a SequentialSpec based on the sequential consistency model. This model requires that operations be applied atomically and that operations within a thread are sequential (they have a total order within the thread).

If you’re not sure whether to pick this or LinearizabilityTester, favor LinearizabilityTester.

§Sequential Consistency

Unlike with linearizability, there is no intrinsic order of operations across threads, even if they are fully sequenced in “real-time” (defined more precisely below). Anomalies are therefore possible as threads do not necessarily agree on viable orders of operations. For example, the later read by Thread 2 in this diagram is allowed to return the value prior to Thread 1’s write even though the operations are seemingly not concurrent:

          -----------Time------------------------------>
Thread 1: [write invoked... and returns]
Thread 2:                                 [read invoked... and returns]

While “real time” is a common way to phrase an implicit total ordering on non-concurrent events spanning threads, a more precise way to think about this is that prior to Thread 2 starting its read, Thread 1 is capable of communicating with Thread 2 indicating that the write finished. This perspective avoids introducing the notion of a shared global time, which is often a misleading perspective when it comes to distributed systems.

The SequentialSpec will imply additional ordering constraints based on semantics specific to each operation. For example, a value cannot be popped off a stack before it is pushed. It is then the responsibility of the checker to establish whether a valid total ordering of events exists under these constraints.

See also: LinearizabilityTester.

Implementations§

Source§

impl<T: Ord, RefObj: SequentialSpec> SequentialConsistencyTester<T, RefObj>

Source

pub fn new(init_ref_obj: RefObj) -> Self

Source

pub fn len(&self) -> usize

Indicates the aggregate number of operations completed or in flight across all threads.

Source§

impl<T, RefObj> SequentialConsistencyTester<T, RefObj>
where T: Copy + Debug + Ord, RefObj: Clone + SequentialSpec, RefObj::Op: Clone + Debug, RefObj::Ret: Clone + Debug + PartialEq,

Source

pub fn serialized_history(&self) -> Option<Vec<(RefObj::Op, RefObj::Ret)>>
where RefObj: Clone, RefObj::Op: Clone, RefObj::Ret: Clone,

Attempts to serialize the recorded partially ordered operation history into a total order that is consistent with a reference object’s operational semantics.

Trait Implementations§

Source§

impl<ThreadId: Clone, RefObj: Clone + SequentialSpec> Clone for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj::Op: Clone, RefObj::Ret: Clone,

Source§

fn clone(&self) -> SequentialConsistencyTester<ThreadId, RefObj>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T, RefObj> ConsistencyTester<T, RefObj> for SequentialConsistencyTester<T, RefObj>
where T: Copy + Debug + Ord, RefObj: Clone + SequentialSpec, RefObj::Op: Clone + Debug, RefObj::Ret: Clone + Debug + PartialEq,

Source§

fn on_invoke( &mut self, thread_id: T, op: RefObj::Op, ) -> Result<&mut Self, String>

Indicates that a thread invoked an operation. Returns Ok(...) if the history is valid, even if it is not sequentially consistent.

See SequentialConsistencyTester::serialized_history.

Source§

fn on_return( &mut self, thread_id: T, ret: RefObj::Ret, ) -> Result<&mut Self, String>

Indicates that a thread’s earlier operation invocation returned. Returns Ok(...) if the history is valid, even if it is not sequentially consistent.

See SequentialConsistencyTester::serialized_history.

Source§

fn is_consistent(&self) -> bool

Indicates whether the recorded history is sequentially consistent.

Source§

fn on_invret( &mut self, thread_id: T, op: RefObj::Op, ret: RefObj::Ret, ) -> Result<&mut Self, String>

A helper that indicates both an operation and corresponding return value for a thread. Returns Ok(...) if the history is valid, even if it is not consistent.
Source§

impl<ThreadId: Debug, RefObj: Debug + SequentialSpec> Debug for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj::Op: Debug, RefObj::Ret: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Ord, RefObj> Default for SequentialConsistencyTester<T, RefObj>
where RefObj: Default + SequentialSpec,

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<ThreadId: Hash, RefObj: Hash + SequentialSpec> Hash for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj::Op: Hash, RefObj::Ret: Hash,

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<ThreadId: PartialEq, RefObj: PartialEq + SequentialSpec> PartialEq for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj::Op: PartialEq, RefObj::Ret: PartialEq,

Source§

fn eq(&self, other: &SequentialConsistencyTester<ThreadId, RefObj>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T, RefObj> Serialize for SequentialConsistencyTester<T, RefObj>
where RefObj: Serialize + SequentialSpec, RefObj::Op: Serialize, RefObj::Ret: Serialize, T: Ord + Serialize,

Available on crate feature serde only.
Source§

fn serialize<Ser: Serializer>(&self, ser: Ser) -> Result<Ser::Ok, Ser::Error>

Serialize this value into the given Serde serializer. Read more
Source§

impl<ThreadId: Eq, RefObj: Eq + SequentialSpec> Eq for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj::Op: Eq, RefObj::Ret: Eq,

Source§

impl<ThreadId, RefObj: SequentialSpec> StructuralPartialEq for SequentialConsistencyTester<ThreadId, RefObj>

Auto Trait Implementations§

§

impl<ThreadId, RefObj> Freeze for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj: Freeze,

§

impl<ThreadId, RefObj> RefUnwindSafe for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj: RefUnwindSafe, ThreadId: RefUnwindSafe, <RefObj as SequentialSpec>::Op: RefUnwindSafe, <RefObj as SequentialSpec>::Ret: RefUnwindSafe,

§

impl<ThreadId, RefObj> Send for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj: Send, ThreadId: Send, <RefObj as SequentialSpec>::Op: Send, <RefObj as SequentialSpec>::Ret: Send,

§

impl<ThreadId, RefObj> Sync for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj: Sync, ThreadId: Sync, <RefObj as SequentialSpec>::Op: Sync, <RefObj as SequentialSpec>::Ret: Sync,

§

impl<ThreadId, RefObj> Unpin for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj: Unpin,

§

impl<ThreadId, RefObj> UnwindSafe for SequentialConsistencyTester<ThreadId, RefObj>
where RefObj: UnwindSafe, ThreadId: RefUnwindSafe, <RefObj as SequentialSpec>::Op: RefUnwindSafe, <RefObj as SequentialSpec>::Ret: RefUnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.