pub struct RcuReadLeaseRegistry<K, T, W> { /* private fields */ }Expand description
Authoritative allocation-indexed registry for physical read permissions.
Each allocation keeps an owner-side RcuLeaseAccumulator. The registry
also records every issued lease and removes its record only when the
matching RcuRegisteredReadLease is returned. Its invariant says that
the accumulator fraction plus all active reader fractions for an allocation
is exactly one. Therefore proving that the allocation has no active record
is sufficient to recover its stored resource.
Implementations§
Source§impl<K, T, W> RcuReadLeaseRegistry<K, T, W>
impl<K, T, W> RcuReadLeaseRegistry<K, T, W>
Sourcepub proof fn empty() -> tracked res : Self
pub proof fn empty() -> tracked res : Self
res.wf(),res.keys() == Set::<K>::empty(),res.active_ids() == Set::<nat>::empty(),res.next_lease() == 0,Creates an empty tracked registry.
Sourcepub proof fn lemma_contains_iff_key(tracked &self, key: K)
pub proof fn lemma_contains_iff_key(tracked &self, key: K)
self.contains(key) <==> self.keys().contains(key),Relates keyed lookup to membership in the registry’s key set.
Sourcepub proof fn lemma_all_contains_iff_keys(tracked &self)
pub proof fn lemma_all_contains_iff_keys(tracked &self)
forall |key: K| #[trigger] self.contains(key) <==> self.keys().contains(key),Relates registry membership to the complete key set for all keys.
Sourcepub closed spec fn accumulator(self, key: K) -> RcuLeaseAccumulator<T>
pub closed spec fn accumulator(self, key: K) -> RcuLeaseAccumulator<T>
self.contains(key),Sourcepub closed spec fn active_ids(self) -> Set<nat>
pub closed spec fn active_ids(self) -> Set<nat>
Sourcepub closed spec fn active_records(self) -> Map<nat, RcuActiveReadLeaseRecord<K, W>>
pub closed spec fn active_records(self) -> Map<nat, RcuActiveReadLeaseRecord<K, W>>
Ghost snapshot used to state the per-allocation accounting invariant.
Sourcepub closed spec fn next_lease(self) -> nat
pub closed spec fn next_lease(self) -> nat
Sourcepub closed spec fn active_record(self, lease_id: nat) -> RcuActiveReadLeaseRecord<K, W>
pub closed spec fn active_record(self, lease_id: nat) -> RcuActiveReadLeaseRecord<K, W>
self.active_ids().contains(lease_id),Sourcepub proof fn tracked_borrow_active_witness(tracked &self, lease_id: nat) -> tracked witness : &W
pub proof fn tracked_borrow_active_witness(tracked &self, lease_id: nat) -> tracked witness : &W
self.active_ids().contains(lease_id),ensures*witness == self.active_record(lease_id).witness(),Borrows the client witness associated with one active lease.
The witness remains owned by the registry until the matching lease is returned. Reclamation proofs use this borrow to show that an allegedly active lease is incompatible with a completed grace period.
Sourcepub proof fn tracked_borrow_active_witness_mut(tracked &mut self, lease_id: nat) -> tracked witness : &mut W
pub proof fn tracked_borrow_active_witness_mut(tracked &mut self, lease_id: nat) -> tracked witness : &mut W
old(self).active_ids().contains(lease_id),ensures*witness == old(self).active_record(lease_id).witness(),final(self).keys() == old(self).keys(),final(self).active_ids() == old(self).active_ids(),final(self).next_lease() == old(self).next_lease(),final(self).active_record(lease_id).key() == old(self).active_record(lease_id).key(),final(self).active_record(lease_id).accumulator_id()
== old(self).active_record(lease_id).accumulator_id(),final(self).active_record(lease_id).fraction()
== old(self).active_record(lease_id).fraction(),final(self).active_record(lease_id).witness() == *final(witness),forall |other: nat| {
other != lease_id && old(self).active_ids().contains(other)
==> final(self).active_record(other) == old(self).active_record(other)
},Mutably borrows an active witness while preserving the registry.
Resource-algebra validation may require a mutable receiver even when its postcondition leaves the witness unchanged.
Sourcepub open spec fn has_active(self, key: K) -> bool
pub open spec fn has_active(self, key: K) -> bool
{
exists |lease_id: nat| {
self.active_ids().contains(lease_id) && self.active_record(lease_id).key() == key
}
}Sourcepub open spec fn wf(self) -> bool
pub open spec fn wf(self) -> bool
{
&&& forall |lease_id: nat| {
#[trigger] self.active_ids().contains(lease_id)
==> {
let record = self.active_record(lease_id);
&&& lease_id < self.next_lease()
&&& self.contains(record.key())
&&& record.accumulator_id() == self.accumulator(record.key()).id()
&&& record.fraction() > 0real
}
}
&&& forall |key: K| {
#[trigger] self.contains(key)
==> self.accumulator(key).fraction()
+ active_lease_fraction(self.active_records(), key, self.next_lease())
== 1real
}
}Sourcepub proof fn insert(tracked &mut self, key: K, tracked resource: T)
pub proof fn insert(tracked &mut self, key: K, tracked resource: T)
old(self).wf(),!old(self).contains(key),ensuresfinal(self).wf(),final(self).keys() == old(self).keys().insert(key),final(self).active_ids() == old(self).active_ids(),final(self).next_lease() == old(self).next_lease(),forall |lease_id: nat| {
old(self).active_ids().contains(lease_id)
==> final(self).active_record(lease_id) == old(self).active_record(lease_id)
},final(self).contains(key),final(self).accumulator(key).resource() == resource,final(self).accumulator(key).fraction() == 1real,forall |other: K| {
old(self).contains(other)
==> final(self).accumulator(other) == old(self).accumulator(other)
},Registers one allocation and stores its complete ownership resource.
Sourcepub proof fn split_lease(
tracked &mut self,
key: K,
tracked witness: W,
) -> tracked lease : RcuRegisteredReadLease<K, T>
pub proof fn split_lease( tracked &mut self, key: K, tracked witness: W, ) -> tracked lease : RcuRegisteredReadLease<K, T>
old(self).wf(),old(self).contains(key),ensuresfinal(self).wf(),final(self).keys() == old(self).keys(),forall |candidate: K| (
#[trigger] final(self).contains(candidate) == old(self).contains(candidate)
),final(self).next_lease() == old(self).next_lease() + 1,lease.lease_id() == old(self).next_lease(),lease.key() == key,final(self).active_ids() == old(self).active_ids().insert(lease.lease_id()),final(self).active_record(lease.lease_id()).key() == key,final(self).active_record(lease.lease_id()).accumulator_id() == lease.accumulator_id(),final(self).active_record(lease.lease_id()).fraction() == lease.fraction(),final(self).active_record(lease.lease_id()).witness() == witness,forall |lease_id: nat| {
old(self).active_ids().contains(lease_id)
==> final(self).active_record(lease_id) == old(self).active_record(lease_id)
},lease.accumulator_id() == old(self).accumulator(key).id(),lease.resource() == old(self).accumulator(key).resource(),lease.fraction() == old(self).accumulator(key).fraction() / 2real,final(self).accumulator(key).id() == old(self).accumulator(key).id(),final(self).accumulator(key).resource() == old(self).accumulator(key).resource(),final(self).accumulator(key).fraction() == old(self).accumulator(key).fraction() / 2real,forall |other: K| {
other != key && old(self).contains(other)
==> final(self).accumulator(other) == old(self).accumulator(other)
},Splits a lease and installs its client witness in the active registry.
Sourcepub proof fn return_lease(tracked &mut self, tracked lease: RcuRegisteredReadLease<K, T>) -> tracked witness : W
pub proof fn return_lease(tracked &mut self, tracked lease: RcuRegisteredReadLease<K, T>) -> tracked witness : W
old(self).wf(),old(self).active_ids().contains(lease.lease_id()),old(self).active_record(lease.lease_id()).key() == lease.key(),old(self).active_record(lease.lease_id()).accumulator_id() == lease.accumulator_id(),old(self).active_record(lease.lease_id()).fraction() == lease.fraction(),ensuresfinal(self).wf(),final(self).keys() == old(self).keys(),forall |candidate: K| (
#[trigger] final(self).contains(candidate) == old(self).contains(candidate)
),final(self).next_lease() == old(self).next_lease(),final(self).active_ids() == old(self).active_ids().remove(lease.lease_id()),witness == old(self).active_record(lease.lease_id()).witness(),forall |lease_id: nat| {
lease_id != lease.lease_id() && old(self).active_ids().contains(lease_id)
==> final(self).active_record(lease_id) == old(self).active_record(lease_id)
},final(self).accumulator(lease.key()).id() == old(self).accumulator(lease.key()).id(),final(self).accumulator(lease.key()).resource()
== old(self).accumulator(lease.key()).resource(),final(self).accumulator(lease.key()).fraction()
== old(self).accumulator(lease.key()).fraction() + lease.fraction(),forall |other: K| {
other != lease.key() && old(self).contains(other)
==> final(self).accumulator(other) == old(self).accumulator(other)
},Returns one lease and removes exactly its matching active record.
Sourcepub proof fn reclaim(tracked &mut self, key: K) -> tracked resource : T
pub proof fn reclaim(tracked &mut self, key: K) -> tracked resource : T
old(self).wf(),old(self).contains(key),!old(self).has_active(key),ensuresfinal(self).wf(),final(self).keys() == old(self).keys().remove(key),final(self).active_ids() == old(self).active_ids(),final(self).active_records() == old(self).active_records(),final(self).next_lease() == old(self).next_lease(),forall |lease_id: nat| {
old(self).active_ids().contains(lease_id)
==> final(self).active_record(lease_id) == old(self).active_record(lease_id)
},!final(self).contains(key),resource == old(self).accumulator(key).resource(),forall |other: K| {
other != key && old(self).contains(other)
==> final(self).accumulator(other) == old(self).accumulator(other)
},Recovers one allocation after a client proof rules out all active leases.
Auto Trait Implementations§
impl<K, T, W> Freeze for RcuReadLeaseRegistry<K, T, W>
impl<K, T, W> RefUnwindSafe for RcuReadLeaseRegistry<K, T, W>
impl<K, T, W> Send for RcuReadLeaseRegistry<K, T, W>
impl<K, T, W> Sync for RcuReadLeaseRegistry<K, T, W>
impl<K, T, W> Unpin for RcuReadLeaseRegistry<K, T, W>
impl<K, T, W> UnsafeUnpin for RcuReadLeaseRegistry<K, T, W>
impl<K, T, W> UnwindSafe for RcuReadLeaseRegistry<K, T, W>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: From<T>,
impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: From<T>,
fn obeys_from_spec() -> bool
fn from_spec(v: T) -> VERUS_SPEC__A
§impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: Into<T>,
impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: Into<T>,
fn obeys_into_spec() -> bool
fn into_spec(self) -> T
§impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
fn obeys_into_spec() -> bool
fn into_spec(self) -> U
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<A> SpecEq<&A> for Awhere
A: ?Sized,
impl<A> SpecEq<&mut A> for Awhere
A: ?Sized,
impl<A> SpecEq<A> for Awhere
A: ?Sized,
impl<A> SpecEq<Ghost<A>> for A
impl<A> SpecEq<Tracked<A>> for A
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.