pub struct AtomicInvariant<K, V, Pred> { /* private fields */ }
Expand description

An AtomicInvariant is a ghost object that provides “interior mutability” for ghost objects, specifically, for tracked ghost objects. A reference &AtomicInvariant may be shared between clients. A client holding such a reference may open the invariant to obtain ghost ownership of v1: V, and then close the invariant by returning ghost ownership of a (potentially) different object v2: V.

An AtomicInvariant implements Sync and may be shared between threads. However, this means that an AtomicInvariant can be only opened for the duration of a single sequentially consistent atomic operation. Such operations are provided by our PAtomic library. For an invariant object without this atomicity restriction, see LocalInvariant, which gives up thread safety in exchange.

An AtomicInvariant consists of:

  • A predicate specified via the InvariantPredicate type bound, that determines what values V may be saved inside the invariant.
  • A constant K, specified at construction type. The predicate function takes this constant as a parameter, so the constant allows users to dynamically configure the predicate function in a way that can’t be done at the type level.
  • A namespace. This is a bit of a technicality, and you can often just declare it as an arbitrary integer with no issues. See the open_local_invariant! documentation for more details.

The constant and namespace are specified at construction time (AtomicInvariant::new). These values are fixed for the lifetime of the AtomicInvariant object. To open the invariant and access the stored object V, use the macro open_atomic_invariant!.

The AtomicInvariant API is an instance of the “invariant” method in Verus’s general philosophy on interior mutability.

Note: Rather than using AtomicInvariant directly, we generally recommend using the atomic_ghost APIs.

Implementations§

source§

impl<K, V, Pred: InvariantPredicate<K, V>> AtomicInvariant<K, V, Pred>

source

pub spec fn constant(&self) -> K

The constant specified upon the initialization of this AtomicInvariant.

source

pub spec fn namespace(&self) -> int

Namespace the invariant was declared in.

source

pub open spec fn inv(&self, v: V) -> bool

{ Pred::inv(self.constant(), v) }

Returns true if it is possible to store the value v into the AtomicInvariant.

This is equivalent to Pred::inv(self.constant(), v).

source

pub proof fn new(k: K, tracked v: V, ns: int) -> AtomicInvariant<K, V, Pred>

requires
Pred::inv(k, v),
ensures
i.constant() == k,
i.namespace() == ns,

Initialize a new AtomicInvariant with constant k. initial stored (tracked) value v, and in the namespace ns.

source

pub proof fn into_inner(self) -> tracked V

ensures
self.inv(v),

Destroys the AtomicInvariant, returning the tracked value contained within.

Auto Trait Implementations§

§

impl<K, V, Pred> RefUnwindSafe for AtomicInvariant<K, V, Pred>

§

impl<K, V, Pred> Send for AtomicInvariant<K, V, Pred>
where V: Send,

§

impl<K, V, Pred> Sync for AtomicInvariant<K, V, Pred>
where V: Send,

§

impl<K, V, Pred> Unpin for AtomicInvariant<K, V, Pred>
where K: Unpin, Pred: Unpin, V: Unpin,

§

impl<K, V, Pred> UnwindSafe for AtomicInvariant<K, V, Pred>

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> 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, U> TryFrom<U> for T
where U: Into<T>,

§

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>,

§

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.