@@ -69,26 +69,30 @@ use verus_builtin::*;
6969use verus_builtin_macros:: * ;
7070use vstd:: prelude:: * ;
7171use vstd:: resource;
72+ use vstd:: resource:: agree:: AgreementRA ;
73+ use vstd:: resource:: algebra;
7274use vstd:: resource:: algebra:: ResourceAlgebra ;
73- use vstd:: resource:: pcm:: Resource ;
75+ use vstd:: resource:: frac:: FractionRA ;
76+ use vstd:: resource:: pcm;
7477use vstd:: resource:: pcm:: PCM ;
78+ use vstd:: resource:: product:: ProductRA ;
7579use vstd:: resource:: update_and_redistribute;
7680use vstd:: resource:: update_mut;
7781use vstd:: resource:: Loc ;
7882
7983verus ! {
8084
81- // A one-shot resource represents one of the following four resources:
82- //
83- // `FullRightToComplete` -- the authority to complete the one-shot;
84- //
85- // `HalfRightToComplete` -- half of the authority to complete the
86- // one-shot, which can be combined with another half to make a full
87- // authority; or
88- //
89- // `Complete` -- knowledge that the one-shot has completed.
90- //
91- // `Empty` - no permission at all.
85+ /// A one-shot resource represents one of the following four resources:
86+ ///
87+ /// `FullRightToComplete` -- the authority to complete the one-shot;
88+ ///
89+ /// `HalfRightToComplete` -- half of the authority to complete the
90+ /// one-shot, which can be combined with another half to make a full
91+ /// authority; or
92+ ///
93+ /// `Complete` -- knowledge that the one-shot has completed.
94+ ///
95+ /// `Empty` - no permission at all.
9296pub enum OneShotResourceValue {
9397 FullRightToComplete ,
9498 HalfRightToComplete ,
@@ -142,7 +146,7 @@ impl PCM for OneShotResourceValue {
142146}
143147
144148pub struct OneShotResource {
145- r: Resource <OneShotResourceValue >,
149+ r: pcm :: Resource <OneShotResourceValue >,
146150}
147151
148152impl OneShotResource {
@@ -162,7 +166,7 @@ impl OneShotResource {
162166 resource@ is FullRightToComplete ,
163167 {
164168 let v = OneShotResourceValue :: FullRightToComplete { } ;
165- let tracked mut r = Resource :: <OneShotResourceValue >:: alloc( v) ;
169+ let tracked mut r = pcm :: Resource :: <OneShotResourceValue >:: alloc( v) ;
166170 OneShotResource { r }
167171 }
168172
@@ -194,7 +198,7 @@ impl OneShotResource {
194198 requires
195199 old( self ) @ is FullRightToComplete ,
196200 ensures
197- self @ is Complete ,
201+ final ( self ) @ is Complete ,
198202 {
199203 let v = OneShotResourceValue :: Complete { } ;
200204 update_mut( & mut self . r, v) ;
@@ -221,10 +225,10 @@ impl OneShotResource {
221225 !( old( other) @ is Empty ) ,
222226 ensures
223227 old( other) @ is HalfRightToComplete ,
224- self @ is Complete ,
225- other@ is Complete ,
226- self . id ( ) == old ( self ) . id ( ) ,
227- other . id ( ) == old ( self ) . id ( ) ,
228+ final ( self ) . id ( ) == old ( self ) . id ( ) ,
229+ final ( other) . id ( ) == old ( self ) . id ( ) ,
230+ final ( self ) @ is Complete ,
231+ final ( other ) @ is Complete ,
228232 {
229233 self . r. validate( ) ;
230234 other. r. validate( ) ;
@@ -258,16 +262,169 @@ impl OneShotResource {
258262 other@ is Complete ,
259263 !( old( self ) @ is Empty ) ,
260264 ensures
261- self . id( ) == old( self ) . id( ) ,
262- self @ == old( self ) @,
263- self @ is Complete ,
265+ final( self ) . id( ) == old( self ) . id( ) ,
266+ final( self ) @ == old( self ) @,
267+ final( self ) @ is Complete ,
268+ {
269+ self . r. validate_2( & other. r) ;
270+ }
271+ }
272+
273+ /// A one-shot resource represents one of the following four resources:
274+ ///
275+ /// `FullRightToComplete` -- the authority to complete the one-shot;
276+ ///
277+ /// `HalfRightToComplete` -- half of the authority to complete the
278+ /// one-shot, which can be combined with another half to make a full
279+ /// authority; or
280+ ///
281+ /// `Complete` -- knowledge that the one-shot has completed.
282+ ///
283+ /// `Empty` - no permission at all.
284+ pub type OneShotCarrier <T > = ProductRA <FractionRA , Option <AgreementRA <T >>>;
285+
286+ pub struct OneShotResource2 <T > {
287+ r: algebra:: Resource <OneShotCarrier <T >>,
288+ }
289+
290+ impl <T > OneShotResource2 <T > {
291+ pub closed spec fn loc( self ) -> Loc {
292+ self . r. loc( )
293+ }
294+
295+ /// The view of the underlying resource
296+ pub closed spec fn view( self ) -> Option <T > {
297+ match self . r. value( ) . right {
298+ Some ( AgreementRA :: Agree ( x) ) => Some ( x) ,
299+ _ => None
300+ }
301+ }
302+
303+ pub closed spec fn fraction( self ) -> real {
304+ self . r. value( ) . left. frac( )
305+ }
306+
307+ pub proof fn alloc( ) -> ( tracked resource: Self )
308+ ensures
309+ resource@ is None ,
310+ resource. fraction( ) == 1 real,
311+ {
312+ let v = OneShotCarrier { left: FractionRA :: new( 1 real) , right: None } ;
313+ let tracked r = algebra:: Resource :: <OneShotCarrier <T >>:: alloc( v) ;
314+ OneShotResource2 { r }
315+ }
316+
317+ /// This function splits full authority to perform a one-shot
318+ /// into two half authorities to perform it.
319+ // TODO(bsdinis): make this using shared ref
320+ pub proof fn split( tracked self ) -> ( tracked r: ( Self , Self ) )
321+ requires
322+ self @ is None ,
323+ self . fraction( ) == 1 real,
324+ ensures
325+ ( {
326+ let ( half1, half2) = r;
327+ &&& half1@ is None
328+ &&& half2@ is None
329+ &&& half1. fraction( ) == 0.5 real
330+ &&& half2. fraction( ) == 0.5 real
331+ &&& half1. loc( ) == self . loc( )
332+ &&& half2. loc( ) == self . loc( )
333+ } ) ,
334+ {
335+ self . r. validate( ) ;
336+ assert( self . r. value( ) . right is None ) ;
337+ let half = OneShotCarrier { left: FractionRA :: new( 0.5 real) , right: self . r. value( ) . right } ;
338+ assert( self . r. value( ) . left == FractionRA :: op( half. left, half. left) ) ;
339+ assert( self . r. value( ) . right == Option :: op( half. right, half. right) ) ;
340+ let tracked ( r1, r2) = self . r. split( half, half) ;
341+ ( OneShotResource2 { r: r1 } , OneShotResource2 { r: r2 } )
342+ }
343+
344+ // This function performs a one-shot given a resource representing
345+ // full authority to complete the one-shot.
346+ //
347+ // Upon return, the passed-in resource will have been transformed
348+ // into knowledge that the one-shot has been performed.
349+ pub proof fn shoot( tracked & mut self , v: T )
350+ requires
351+ old( self ) @ is None ,
352+ old( self ) . fraction( ) == 1 real,
353+ ensures
354+ final( self ) @ == Some ( v)
355+ {
356+ let new_carrier = OneShotCarrier { left: self . r. value( ) . left, right: Some ( AgreementRA :: Agree ( v) ) } ;
357+ // TODO(bsdinis): need the resource lib
358+ // update_mut(&mut self.r, new_carrier);
359+ admit( )
360+ }
361+
362+ // This function performs a one-shot given two resources, the
363+ // first of which represents an incomplete one-shot (and half the
364+ // authority needed to perform it). The resources must have the
365+ // same `loc()`, meaning they're talking about the same one-shot.
366+ //
367+ // Upon return, the passed-in resources will have both been
368+ // transformed into knowledge that the one-shot has been
369+ // performed.
370+ //
371+ // The caller of this function only needs to know that `self`
372+ // provides half authority and that `other` isn't `Empty`. Upon
373+ // return the caller will learn that *both* the resources had
374+ // provided half authority at call time. However, those resources
375+ // were transformed so they don't provide that authority anymore.
376+ pub proof fn shoot_with_two_halves( tracked & mut self , tracked other: & mut Self , v: T )
377+ requires
378+ old( other) . loc( ) == old( self ) . loc( ) ,
379+ old( self ) @ is None ,
380+ old( self ) . fraction( ) + old( other) . fraction( ) == 1 real,
381+ ensures
382+ old( other) @ is None ,
383+ final( self ) . loc( ) == old( self ) . loc( ) ,
384+ final( other) . loc( ) == old( self ) . loc( ) ,
385+ final( self ) . fraction( ) == old( self ) . fraction( ) ,
386+ final( other) . fraction( ) == old( other) . fraction( ) ,
387+ final( self ) @ == Some ( v) ,
388+ final( other) @ == Some ( v) ,
389+ {
390+ self . r. validate_2( & other. r) ;
391+ let new_self_carrier = OneShotCarrier { left: self . r. value( ) . left, right: Some ( AgreementRA :: Agree ( v) ) } ;
392+ let new_other_carrier = OneShotCarrier { left: other. r. value( ) . left, right: Some ( AgreementRA :: Agree ( v) ) } ;
393+ // TODO(bsdinis): we want the full lib for ras too
394+ // update_and_redistribute(&mut self.r, &mut other.r, v, v);
395+ admit( )
396+ }
397+
398+ // This function duplicates a one-shot resource representing knowledge of completion.
399+ pub proof fn duplicate( tracked self ) -> ( tracked r: ( Self , Self ) )
400+ requires
401+ self @ is Some ,
402+ ensures
403+ r. 0 . loc( ) == self . loc( ) ,
404+ r. 1 . loc( ) == self . loc( ) ,
405+ r. 0 @ == self @,
406+ r. 1 @ == self @,
407+ {
408+ self . r. validate( ) ;
409+ let half = OneShotCarrier { left: FractionRA :: new( self . fraction( ) /2 real) , right: self . r. value( ) . right } ;
410+ let tracked ( r1, r2) = self . r. split( half, half) ;
411+ ( OneShotResource2 { r: r1 } , OneShotResource2 { r: r2 } )
412+ }
413+
414+ pub proof fn lemma_agree( tracked & mut self , tracked other: & Self )
415+ requires
416+ other. loc( ) == old( self ) . loc( ) ,
417+ other@ is Some ,
418+ ensures
419+ final( self ) . loc( ) == old( self ) . loc( ) ,
420+ final( self ) @ == old( self ) @,
264421 {
265422 self . r. validate_2( & other. r) ;
266423 }
267424}
268425
269426// This example illustrates some uses of the one-shot functions.
270- fn main ( ) {
427+ fn test_manual ( ) {
271428 let tracked full = OneShotResource :: alloc( ) ;
272429 proof {
273430 full. perform( ) ;
@@ -292,4 +449,33 @@ fn main() {
292449 assert( knowledge@ is Complete ) ;
293450}
294451
452+ fn test_combinator( ) {
453+ let tracked full = OneShotResource2 :: <int>:: alloc( ) ;
454+ proof {
455+ full. shoot( 2 ) ;
456+ }
457+ assert( full@ == Some ( 2 int) ) ;
458+ let tracked different_oneshot = OneShotResource2 :: <int>:: alloc( ) ;
459+ let tracked ( mut half1, mut half2) = different_oneshot. split( ) ;
460+ let ghost id = half1. loc( ) ;
461+ assert( half1. loc( ) == half2. loc( ) ) ;
462+ assert( half1@ is None ) ;
463+ assert( half2@ is None ) ;
464+ assert( half1. fraction( ) == 0.5 real) ;
465+ assert( half2. fraction( ) == 0.5 real) ;
466+ proof {
467+ half1. shoot_with_two_halves( & mut half2, 3 ) ;
468+ }
469+ assert( half1. loc( ) == id) ;
470+ assert( half2. loc( ) == id) ;
471+ assert( half1@ == Some ( 3 int) ) ;
472+ assert( half2@ == Some ( 3 int) ) ;
473+ /* TODO(bsdinis): need shared refs
474+ let tracked knowledge = half1.duplicate();
475+ assert(knowledge.loc() == id);
476+ assert(half1.loc() == id);
477+ assert(knowledge@ is Complete);
478+ */
479+ }
480+
295481} // verus!
0 commit comments