vstd_extra/resource/ghost_resource/
excl.rs1use vstd::modes::tracked_swap;
3use vstd::pcm::*;
4use vstd::prelude::*;
5use vstd::storage_protocol::StorageResource;
6
7use super::super::pcm::excl::*;
8use super::super::storage_protocol::excl::*;
9
10verus! {
11
12pub type UniqueToken = ExclusiveGhost<()>;
13
14pub tracked struct ExclusiveGhost<T>(Resource<ExclR<T>>);
17
18impl<T> ExclusiveGhost<T> {
19 pub closed spec fn id(self) -> Loc {
21 self.0.loc()
22 }
23
24 pub closed spec fn pcm(self) -> ExclR<T> {
26 self.0.value()
27 }
28
29 pub open spec fn value(self) -> T {
31 self.pcm().value()
32 }
33
34 pub open spec fn view(self) -> T {
36 self.value()
37 }
38
39 pub open spec fn wf(self) -> bool {
41 self.pcm() is Excl
42 }
43
44 #[verifier::type_invariant]
45 closed spec fn type_inv(self) -> bool {
46 self.wf()
47 }
48
49 spec fn type_inv_inner(r: ExclR<T>) -> bool {
50 r is Excl
51 }
52
53 pub proof fn alloc(value: T) -> (tracked res: Self)
55 ensures
56 res.view() == value,
57 res.wf(),
58 {
59 Self(Resource::<ExclR<T>>::alloc(ExclR::Excl(value)))
60 }
61
62 pub proof fn update(tracked &mut self, value: T) -> (res: T)
64 ensures
65 self.id() == old(self).id(),
66 self.view() == value,
67 self.wf(),
68 {
69 use_type_invariant(&*self);
70 Self::update_helper(&mut self.0, value)
71 }
72
73 proof fn update_helper(tracked r: &mut Resource<ExclR<T>>, value: T) -> (res: T)
74 requires
75 Self::type_inv_inner(old(r).value()),
76 old(r).value() is Excl,
77 ensures
78 Self::type_inv_inner(r.value()),
79 r.value() is Excl,
80 r.loc() == old(r).loc(),
81 res == old(r).value().value(),
82 r.value().value() == value,
83 {
84 let ghost res = r.value().value();
85 let tracked mut tmp = Resource::<ExclR<T>>::alloc(ExclR::Unit);
86 tracked_swap(r, &mut tmp);
87 let tracked mut r1 = tmp.update(ExclR::Excl(value));
88 tracked_swap(r, &mut r1);
89 res
90 }
91
92 pub proof fn validate_with_other(tracked &mut self, tracked other: &Self)
94 ensures
95 *old(self) == *self,
96 self.id() != other.id(),
97 self.wf(),
98 {
99 use_type_invariant(&*self);
100 use_type_invariant(other);
101 if self.id() == other.id() {
102 self.0.validate_2(&other.0);
103 }
104 }
105
106 pub proof fn validate(tracked &self)
108 ensures
109 self.wf(),
110 {
111 use_type_invariant(self);
112 }
113}
114
115pub tracked struct Exclusive<T> {
119 tracked r: StorageResource<(), T, ExclP<T>>,
120}
121
122impl<T> Exclusive<T> {
123 pub closed spec fn id(self) -> Loc {
125 self.r.loc()
126 }
127
128 pub closed spec fn protocol_monoid(self) -> ExclP<T> {
130 self.r.value()
131 }
132
133 pub open spec fn resource(self) -> T {
135 self.protocol_monoid().value()
136 }
137
138 pub open spec fn wf(self) -> bool {
140 self.protocol_monoid() is Excl
141 }
142
143 pub open spec fn has_resource(self) -> bool {
145 self.protocol_monoid()->Excl_0 is Some
146 }
147
148 pub open spec fn has_no_resource(self) -> bool {
150 self.protocol_monoid()->Excl_0 is None
151 }
152
153 #[verifier::type_invariant]
154 closed spec fn type_inv(self) -> bool {
155 self.wf()
156 }
157
158 closed spec fn type_inv_inner(r: ExclP<T>) -> bool {
159 r is Excl
160 }
161
162 pub proof fn validate_with_other(tracked &mut self, tracked other: &Self)
164 ensures
165 *old(self) == *self,
166 self.wf(),
167 self.id() != other.id(),
168 {
169 use_type_invariant(&*self);
170 use_type_invariant(other);
171 if self.id() == other.id() {
172 self.r.validate_with_shared(&other.r);
173 }
174 }
175
176 pub proof fn tracked_borrow(tracked &self) -> (tracked res: &T)
178 requires
179 self.has_resource(),
180 ensures
181 *res == self.resource(),
182 {
183 use_type_invariant(&*self);
184 StorageResource::guard(&self.r, map![() => self.resource()]).tracked_borrow(())
185 }
186
187 pub proof fn take_resource(tracked &mut self) -> (tracked res: T)
189 requires
190 old(self).has_resource(),
191 ensures
192 self.has_no_resource(),
193 res == old(self).resource(),
194 self.wf(),
195 {
196 use_type_invariant(&*self);
197 Self::take_resource_helper(&mut self.r)
198 }
199
200 proof fn take_resource_helper(tracked r: &mut StorageResource<(), T, ExclP<T>>) -> (tracked res:
201 T)
202 requires
203 Self::type_inv_inner(old(r).value()),
204 old(r).value()->Excl_0 is Some,
205 ensures
206 Self::type_inv_inner(r.value()),
207 r.value()->Excl_0 is None,
208 r.loc() == old(r).loc(),
209 res == old(r).value()->Excl_0->Some_0,
210 {
211 let tracked mut tmp = StorageResource::<(), T, ExclP<T>>::alloc(
212 ExclP::Unit,
213 Map::tracked_empty(),
214 );
215 tracked_swap(r, &mut tmp);
216 let tracked (mut r1, mut r2) = tmp.withdraw(
217 ExclP::Excl(None),
218 map![()=> tmp.value().value()],
219 );
220 tracked_swap(r, &mut r1);
221 r2.tracked_remove(())
222 }
223
224 pub proof fn put_resource(tracked &mut self, tracked value: T)
226 requires
227 old(self).has_no_resource(),
228 ensures
229 self.has_resource(),
230 self.resource() == value,
231 self.wf(),
232 {
233 use_type_invariant(&*self);
234 Self::put_resource_helper(&mut self.r, value)
235 }
236
237 proof fn put_resource_helper(tracked r: &mut StorageResource<(), T, ExclP<T>>, tracked value: T)
238 requires
239 Self::type_inv_inner(old(r).value()),
240 old(r).value()->Excl_0 is None,
241 ensures
242 Self::type_inv_inner(r.value()),
243 r.value()->Excl_0 is Some,
244 r.loc() == old(r).loc(),
245 r.value()->Excl_0->Some_0 == value,
246 {
247 let ghost g = value;
248 let tracked mut tmp = StorageResource::<(), T, ExclP<T>>::alloc(
249 ExclP::Unit,
250 Map::tracked_empty(),
251 );
252 tracked_swap(r, &mut tmp);
253 let tracked mut m = Map::tracked_empty();
254 m.tracked_insert((), value);
255 tmp.value().lemma_deposits(g);
256 let tracked mut r1 = tmp.deposit(m, ExclP::Excl(Some(g)));
257 tracked_swap(r, &mut r1);
258 }
259
260 pub proof fn update(tracked &mut self, tracked value: T) -> (tracked res: Option<T>)
262 ensures
263 self.has_resource(),
264 self.resource() == value,
265 res == if old(self).has_resource() {
266 Some(old(self).resource())
267 } else {
268 None
269 },
270 self.wf(),
271 {
272 use_type_invariant(&*self);
273 let tracked mut res = None;
274 if self.has_resource() {
275 res = Some(self.take_resource());
276 }
277 self.put_resource(value);
278 res
279 }
280}
281
282}