diff --git a/_CoqProject b/_CoqProject index 700e7c386dddbe3cb9e220209bda79c7196039b7..16fda88572bd3a96b697c6dfcff9e4e6a38bbefd 100644 --- a/_CoqProject +++ b/_CoqProject @@ -21,6 +21,7 @@ theories/lang/new_delete.v theories/lang/swap.v theories/lang/lock.v theories/lang/spawn.v +theories/lang/arc_cmra.v theories/lang/arc.v theories/typing/base.v theories/typing/lft_contexts.v diff --git a/theories/lang/arc.v b/theories/lang/arc.v index abcbd550b3e1219828e5cbad5bcd499547dc2701..92fc2278086f5a94b7883e41516839f80a210049 100644 --- a/theories/lang/arc.v +++ b/theories/lang/arc.v @@ -3,7 +3,7 @@ From iris.base_logic.lib Require Import invariants. From iris.proofmode Require Import tactics. From iris.bi Require Import fractional. From iris.algebra Require Import excl csum frac auth agree. -From lrust.lang Require Import notation new_delete. +From lrust.lang Require Import notation new_delete arc_cmra. From gpfsl.gps Require Import middleware protocols. Set Default Proof Using "Type". @@ -125,640 +125,6 @@ Definition try_unwrap_full : val := else #1 else #2. -(* Lattice of sets with subseteq *) -Program Canonical Structure gset_Lat (A: Type) `{Countable A} := - Make_Lat (gset A) (≡) subseteq union intersection - _ _ _ _ _ _ _ _ _ _ _ _ _. -Next Obligation. move => ???. by apply union_subseteq_l. Qed. -Next Obligation. move => ???. by apply union_subseteq_r. Qed. -Next Obligation. move => ???. by apply union_least. Qed. -Next Obligation. move => ???. by apply intersection_subseteq_l. Qed. -Next Obligation. move => ???. by apply intersection_subseteq_r. Qed. -Next Obligation. move => ??????. by apply intersection_greatest. Qed. - -Instance gset_Lat_bot `{Countable A} : LatBottom (∅ : gset_Lat A). -Proof. done. Qed. - -(** The CMRAs we need. *) - -(* This cmra tracks what the arc must have done by itself when it is the unique clone. - - Self here means that the cmra is updated when the caller moves its own counter, - e.g. the strong arc modifying the strong counter, or the weak arc modifying - the weak counter. - For the strong counter, it tracks the actions: moving 1 to 0 - (the last release/drop), and 1 to 2 (the unique clone). - For the weak counter, it tracks the self actions: moving 1 to -1 (locking), - moving 1 to 0 (the last drop), and 1 to 2 (the unique clone). - - The authority should only be updated when having full fraction, - i.e. the caller being unique. A persistent certificate is issued when the - authority is updated. A fraction of the authority must have seen all certificates. *) -Definition move_selfUR := - prodUR (authUR (optionUR (prodR fracR (agreeR (latC (gset_Lat time)))))) - (authUR (latUR (gset_Lat time))). - -(* This cmra tracks what the arc has asked the other to do, e.g., the weak arc - asks the strong counter to increment when upgrading, or the strong arc asks - the weak counter to increment when downgrading. - - The authority part is owned by the caller, and issue a certificate for - the callee to store in its update. There can be multiple authorities, - each is owned by one caller. A fraction of the authority can issue certificates, - while only the full fraction authority is guaranteed to have seen all certificates. *) -Definition move_otherUR := - prodUR (authUR (optionUR (prodR fracR (latR (gset_Lat time))))) - (authUR (latUR (gset_Lat time))). - -(* This cmra tracks states of the weak counter: - - (None, None) : no strong or weak arc, v = 0. - - (None, Some Cinl (q,n)) : no strong arc, n weak arcs that use q permission, - v = n. - - (None, Some Cinr q) : no strong arc, no weak arc, the weak counter is locked - with a payload of q from a strong arc, v = -1. This state is IMPOSSIBLE. - - (Some 1, None) : some strong arcs, no weak arcs, v = 1. - - (Some 1, Some Cinl (q,n)) : some strong arcs, n weak arcs that use q, v = S n. - - (Some 1, Some Cinr q) : some strong arcs, no weak arc, the weak counter is - locked with a payload of q from a strong arc, v = -1. -*) - -Definition weak_stUR := - prodUR (optionUR fracR) - (optionUR (csumR (prodR fracR positiveR) (prodR (exclR unitC) (agreeR fracC)))). - -(* This cmra tracks states of the strong counter: - - None: no strong arc, v = 0. - - Some (q,n): n strong arcs that took out q, v = n. *) -Definition strong_stUR := - optionUR (prodR fracR positiveR). - -(* The final cmra has 5 components - (strong arc states, weak arc states), - (strong arc self, strong arc downgrade), - (weak arc upgrade) *) -Definition arcUR := - prodUR (prodUR (authUR strong_stUR) (authUR weak_stUR)) - (prodUR (prodUR move_selfUR move_otherUR) move_otherUR). - -Class arcG Σ := { - ArcStG :> inG Σ arcUR; - ArcPrt_gpsG :> gpsG Σ unitProtocol; -}. -Definition arcΣ : gFunctors := #[GFunctor arcUR; gpsΣ unitProtocol]. -Instance subG_arcΣ {Σ} : subG arcΣ Σ → arcG Σ. -Proof. solve_inG. Qed. - -Definition Z_of_arcweak_st (st : weak_stUR) : Z := - match st with - | (None, None) => 0 - | (Some _, None) => 1 - | (None, Some (Cinl (_, n))) => Zpos n - | (Some _, Some (Cinl (_, n))) => Zpos n +1 - | (_, Some _) => -1 - end. - -Definition Z_of_arcstrong_st (st : strong_stUR) : Z := - match st with - | None => 0 - | Some (_, n) => Zpos n - end. - - -Lemma strong_stUR_value st: 0 ≤ Z_of_arcstrong_st st. -Proof. destruct st as [[]|]; simpl; lia. Qed. - -Lemma weak_stUR_value st: -1 ≤ Z_of_arcweak_st st. -Proof. destruct st as [[|] [[[]| |]|]]; simpl; lia. Qed. - -Notation agown γ st := (⎡ own γ (st : arcUR) ⎤ : vProp _)%I. -Notation awk_n st := ((ε, ◯ (st : weak_stUR)), ε). - -Section ArcGhost. - Context `{inG Σ arcUR}. - Local Notation vProp := (vProp Σ). - Implicit Types (Mt Ut Dt: gset time). - - Definition StrongAuth γ (st : strong_stUR) := - agown γ ((● st, ε), ε). - Definition StrongTok γ q := - agown γ ((◯ Some (q, xH), ε), ε). - Definition StrongMoveAuth γ Mt := - agown γ (ε, (((● Some (1%Qp, to_agree $ to_latT Mt), ● to_latT Mt) : move_selfUR, ε), ε)). - Definition StrMoves γ (q: frac) Mt := - agown γ (ε, (((◯ Some (q, to_agree $ to_latT Mt), ε) : move_selfUR, ε), ε)). - Definition StrongDownAuth γ Dt := - agown γ (ε, ((ε, (● Some (1%Qp, to_latT Dt), ● to_latT Dt) : move_otherUR), ε)). - Definition StrDowns γ (q: frac) Dt := - agown γ (ε, ((ε, (◯ Some (q, to_latT Dt), ε) : move_otherUR), ε)). - Definition StrMoveCertS γ Mt : vProp := - agown γ (ε, (((ε, ◯ to_latT Mt) : move_selfUR, ε), ε)). - Definition StrDownCertS γ Mt : vProp := - agown γ (ε, ((ε, (ε, ◯ to_latT Mt) : move_otherUR), ε)). - Definition StrMoveCert γ t := StrMoveCertS γ {[t : time]}. - Definition StrDownCert γ t := StrDownCertS γ {[t : time]}. - - Definition WeakAuth γ (st : weak_stUR) := - agown γ ((ε, ● st), ε). - Definition WeakTok γ q := - agown γ ((ε, ◯ (ε, Some (Cinl (q, xH)))), ε). - Definition WeakUpAuth γ Ut := - agown γ (ε, (ε, (● Some (1%Qp, to_latT Ut), ● to_latT Ut) : move_otherUR)). - Definition WkUps γ (q: frac) Ut := - agown γ (ε, (ε, (◯ Some (q, to_latT Ut), ε) : move_otherUR)). - Definition WkUpCertS γ Mt := - agown γ (ε, (ε, (ε, ◯ to_latT Mt) : move_otherUR)). - Definition WkUpCert γ t := WkUpCertS γ {[t : time]}. - Definition WkLock γ q := - agown γ (ε, ◯ (ε, Some $ Cinr (Excl(), to_agree q)),ε) . - - Global Instance StrMoveCertS_persistent γ Mt : Persistent (StrMoveCertS γ Mt). - Proof. apply embed_persistent, own_core_persistent, pair_core_id; by apply _. Qed. - Global Instance StrDownCertS_persistent γ Mt : Persistent (StrDownCertS γ Mt). - Proof. apply embed_persistent, own_core_persistent, pair_core_id; by apply _. Qed. - Global Instance WkUpCertS_persistent γ Mt : Persistent (WkUpCertS γ Mt). - Proof. apply embed_persistent, own_core_persistent, pair_core_id; by apply _. Qed. - Global Instance StrMoves_fractional γ Mt : Fractional (λ q, StrMoves γ q Mt). - Proof. - rewrite /Fractional => p q. rewrite -embed_sep -own_op. - apply embed_proper, own.own_proper. - apply pair_proper; [done|]. do 3 (apply pair_proper; [|done]). simpl. - by rewrite -auth_frag_op -Some_op pair_op frac_op' agree_idemp. - Qed. - Global Instance StrMoves_asfractional γ q Mt : - AsFractional (StrMoves γ q Mt) (λ q, StrMoves γ q Mt) q. - Proof. split. done. apply _. Qed. - Global Instance StrDowns_fractional γ Dt : Fractional (λ q, StrDowns γ q Dt). - Proof. - rewrite /Fractional => p q. rewrite -embed_sep -own_op. - apply embed_proper, own.own_proper. - apply pair_proper; [done|]. apply pair_proper; [|done]. - rewrite /=. setoid_rewrite pair_op. apply pair_proper; [done|]. - rewrite pair_op. apply pair_proper; [|done]. - by rewrite -auth_frag_op -Some_op pair_op frac_op' lat_op_join' lat_join_idem_L. - Qed. - Global Instance StrDowns_asfractional γ q Dt : - AsFractional (StrDowns γ q Dt) (λ q, StrDowns γ q Dt) q. - Proof. split. done. apply _. Qed. - Global Instance WkUps_fractional γ Ut : Fractional (λ q, WkUps γ q Ut). - Proof. - rewrite /Fractional => p q. rewrite -embed_sep -own_op. - apply embed_proper, own.own_proper. - do 2 (apply pair_proper; [done|]). - rewrite /=. setoid_rewrite pair_op. apply pair_proper; [|done]. - by rewrite -auth_frag_op -Some_op pair_op frac_op' lat_op_join' lat_join_idem_L. - Qed. - Global Instance WkUps_asfractional γ q Ut : - AsFractional (WkUps γ q Ut) (λ q, WkUps γ q Ut) q. - Proof. split. done. apply _. Qed. - - (* move_self *) - Local Notation moveSAuth Mt - := ((● Some (1%Qp, to_agree $ to_latT Mt), ● to_latT Mt) : move_selfUR). - Local Notation moveSMain q Mt - := ((◯ Some (q, to_agree $ to_latT Mt), ε) : move_selfUR). - Local Notation certS Mt - := ((ε, ◯ to_latT Mt) : move_selfUR). - - Lemma arc_ghost_move_self_main_valid Mt1 Mt2 q: - ✓ (moveSAuth Mt1 ⋅ moveSMain q Mt2) → Mt2 = Mt1. - Proof. - rewrite pair_op right_id_L. - move => [/= /auth_valid_discrete_2 [/Some_included - [[_ /= /to_agree_inj /to_latT_inj /leibniz_equiv_iff //]| - /prod_included[_ /to_agree_included /to_latT_inj /leibniz_equiv_iff //]]_]_]. - Qed. - - Lemma arc_ghost_move_self_cert_valid Mt1 Mt2: - ✓ (moveSAuth Mt1 ⋅ certS Mt2) → Mt2 ⊆ Mt1. - Proof. rewrite pair_op => [[_ /auth_valid_discrete_2 [/latT_included // _]]]. Qed. - - Lemma StrongMoveAuth_agree γ Mt q Mt': - StrongMoveAuth γ Mt ∗ StrMoves γ q Mt' -∗ ⌜Mt = Mt'⌝. - Proof. - rewrite -embed_sep -own_op. - iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. - move : VALID => [/=_ [/= ]]. rewrite pair_op. - move => [/= /arc_ghost_move_self_main_valid //]. - Qed. - - Lemma StrMoves_agree γ Mt Mt' q q': - StrMoves γ q Mt ∗ StrMoves γ q' Mt' -∗ ⌜Mt = Mt'⌝. - Proof. - rewrite -embed_sep -own_op. - iIntros "own". iDestruct (own_valid with "own") as %VAL. iPureIntro. - move : VAL => [/=_ [/= [[VAL _]_]_]]. move :VAL. - rewrite /= -auth_frag_op -Some_op pair_op auth_valid_discrete /= Some_valid. - move => [_ /agree_op_inv' /to_latT_inj /leibniz_equiv_iff // ]. - Qed. - - Lemma StrongMoveAuth_Cert_include γ Mt Mt': - StrongMoveAuth γ Mt ∗ StrMoveCertS γ Mt' -∗ ⌜Mt' ⊆ Mt⌝. - Proof. - rewrite -embed_sep -own_op. - iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. - move :VALID => [/= _ [/= ]]. rewrite pair_op. - move => [/= /arc_ghost_move_self_cert_valid //]. - Qed. - - Lemma StrMoves_update γ Mt Mt': - StrongMoveAuth γ Mt ∗ StrMoves γ 1%Qp Mt ==∗ - StrongMoveAuth γ (Mt ∪ Mt') ∗ StrMoves γ 1%Qp (Mt ∪ Mt') ∗ StrMoveCertS γ Mt'. - Proof. - rewrite -3!embed_sep -3!own_op. iIntros "own". - iMod (own_update with "own") as "$"; [|done]. - apply prod_update; [done|]. - apply prod_update; [|rewrite /= left_id right_id //]. - setoid_rewrite pair_op. rewrite /=. - apply prod_update; [|rewrite /= left_id right_id //]. - rewrite /= 2!pair_op /= 2!right_id left_id. - apply prod_update; simpl. - - by apply auth_update, option_local_update, exclusive_local_update. - - apply auth_update_alloc. - rewrite -(right_id_L ε op (to_latT Mt')) -lat_op_join' cmra_comm. - by apply op_local_update_discrete. - Qed. - - (* move_other *) - Local Notation moveOAuth Mt := ((● Some (1%Qp, to_latT Mt), ● to_latT Mt) : move_otherUR). - Local Notation moveOMain q Mt := ((◯ Some (q, to_latT Mt), ε) : move_otherUR). - Local Notation certO Mt := ((ε, ◯ to_latT Mt) : move_otherUR). - - Lemma arc_ghost_move_other_main_valid Mt1 Mt2: - ✓ (moveOAuth Mt1 ⋅ moveOMain 1%Qp Mt2) → Mt2 = Mt1. - Proof. - rewrite pair_op. - move => [/= /auth_valid_discrete_2 [/Some_included - [[/= _ /to_latT_inj /leibniz_equiv_iff //]| - /prod_included [/= /frac_included /= // _]]]]. - Qed. - - Lemma arc_ghost_move_other_cert_valid Mt1 Mt2: - ✓ (moveOAuth Mt1 ⋅ certO Mt2) → Mt2 ⊆ Mt1. - Proof. - rewrite pair_op right_id_L. - move => [/= _ /auth_valid_discrete_2 [/latT_included // ]]. - Qed. - - Lemma StrongDownAuth_agree γ Dt Dt': - StrongDownAuth γ Dt ∗ StrDowns γ 1%Qp Dt' -∗ ⌜Dt = Dt'⌝. - Proof. - rewrite -embed_sep -own_op. - iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. - move : VALID => [/=_ [/= [/= _ /arc_ghost_move_other_main_valid //]]]. - Qed. - - Lemma StrongDownAuth_Cert_include γ Dt Dt': - StrongDownAuth γ Dt ∗ StrDownCertS γ Dt' -∗ ⌜Dt' ⊆ Dt⌝. - Proof. - rewrite -embed_sep -own_op. - iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. - move :VALID => [/= _ [/= [/= _ /arc_ghost_move_other_cert_valid //]]]. - Qed. - - Lemma StrDowns_forget γ q q' Dt Dt': - StrDowns γ (q + q')%Qp (Dt ∪ Dt') ≡ - (StrDowns γ q (Dt ∪ Dt') ∗ StrDowns γ q' Dt')%I. - Proof. - rewrite -embed_sep -own_op. apply embed_proper, own.own_proper. - do 2 (apply pair_proper; [done|]; apply pair_proper; [|done]). - simpl. rewrite -auth_frag_op -Some_op pair_op -frac_op' lat_op_join'. - rewrite (lat_le_join_l_L (Dt ∪ Dt') Dt'); [done|solve_lat]. - Qed. - - Lemma WeakUpAuth_agree γ Ut Ut': - WeakUpAuth γ Ut ∗ WkUps γ 1%Qp Ut' -∗ ⌜Ut = Ut'⌝. - Proof. - rewrite -embed_sep -own_op. - iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. - move : VALID => [/=_ [/= _ /arc_ghost_move_other_main_valid //]]. - Qed. - - Lemma WeakUpAuth_Cert_include γ Ut Ut': - WeakUpAuth γ Ut ∗ WkUpCertS γ Ut' -∗ ⌜Ut' ⊆ Ut⌝. - Proof. - rewrite -embed_sep -own_op. - iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. - move :VALID => [/= _ [/= _ /arc_ghost_move_other_cert_valid //]]. - Qed. - - Lemma WkUps_forget γ q q' Ut Ut': - WkUps γ (q + q')%Qp (Ut ∪ Ut') ≡ - (WkUps γ q (Ut ∪ Ut') ∗ WkUps γ q' Ut')%I. - Proof. - rewrite -embed_sep -own_op. apply embed_proper, own.own_proper. - do 2 (apply pair_proper; [done|]). apply pair_proper; [|done]. simpl. - rewrite -auth_frag_op -Some_op pair_op -frac_op' lat_op_join'. - rewrite (lat_le_join_l_L (Ut ∪ Ut') Ut'); [done|solve_lat]. - Qed. - - Lemma StrDowns_join γ Dt Dt' q q' : - StrDowns γ (q + q')%Qp (Dt ∪ Dt') ≡ - (StrDowns γ q Dt ∗ StrDowns γ q' Dt')%I. - Proof. - rewrite -embed_sep -own_op. apply embed_proper, own.own_proper. - do 2 (apply pair_proper; [done|]; apply pair_proper; [|done]). - simpl. by rewrite -auth_frag_op -Some_op pair_op -frac_op' lat_op_join'. - Qed. - - Lemma StrDowns_update γ Dt1 Dt2 Dt' q : - StrongDownAuth γ Dt1 ∗ StrDowns γ q Dt2 ==∗ - StrongDownAuth γ (Dt1 ⊔ Dt') ∗ StrDowns γ q (Dt2 ⊔ Dt') ∗ StrDownCertS γ Dt'. - Proof. - rewrite -3!embed_sep -3!own_op. iIntros "own". - iMod (own_update with "own") as "$"; [|done]. - apply prod_update; [done|]. simpl. - apply prod_update; [|rewrite /= !right_id //]. - setoid_rewrite pair_op. rewrite /=. - apply prod_update; [rewrite /= !right_id //|]. - rewrite /= 2!pair_op /= 2!right_id_L left_id_L. rewrite -2!lat_op_join'. - apply prod_update; simpl. - - apply auth_update, option_local_update, prod_local_update_2. - rewrite (cmra_comm_L (to_latT Dt1)) (cmra_comm_L (to_latT Dt2)). - by apply op_local_update_discrete. - - apply auth_update_alloc. - rewrite cmra_comm_L -{2}(right_id_L ε op (to_latT Dt')). - by apply op_local_update_discrete. - Qed. - - Lemma WkUps_join γ Ut Ut' q q' : - WkUps γ (q + q')%Qp (Ut ∪ Ut') ≡ - (WkUps γ q Ut ∗ WkUps γ q' Ut')%I. - Proof. - rewrite -embed_sep -own_op. apply embed_proper, own.own_proper. - by do 3 (apply pair_proper; [done|]). - Qed. - - Lemma WkUps_full_exclusive γ q Ut' : - (∃ Ut, WkUps γ 1%Qp Ut) -∗ WkUps γ q Ut' -∗ False. - Proof. - iDestruct 1 as (Ut) "WU". iIntros "WU'". - iDestruct (WkUps_join with "[$WU $WU']") as "WU". - iDestruct (@own_valid _ arcUR with "WU") - as %[_ [_ [[VAL _]%auth_valid_discrete _]]]. - iPureIntro. simpl in VAL. - have Lt: (1%Qp < (1%Qp + q)%Qp)%Qc. apply Qp_lt_sum. by eexists. - apply (irreflexive_eq (R:= Qclt) 1%Qp 1%Qp); [done|]. - eapply Qclt_le_trans; [apply Lt|done]. - Qed. - - Lemma WkUps_update γ Ut1 Ut2 Ut' q : - WeakUpAuth γ Ut1 ∗ WkUps γ q Ut2 ==∗ - WeakUpAuth γ (Ut1 ⊔ Ut') ∗ WkUps γ q (Ut2 ⊔ Ut') ∗ WkUpCertS γ Ut'. - Proof. - rewrite -3!embed_sep -3!own_op. iIntros "own". - iMod (own_update with "own") as "$"; [|done]. - apply prod_update; [done|]. simpl. - apply prod_update; [rewrite /= !right_id //|]. - apply prod_update; rewrite /=. - - apply auth_update, option_local_update, prod_local_update_2. - rewrite -2!lat_op_join' (cmra_comm_L (to_latT Ut1)) (cmra_comm_L (to_latT Ut2)). - by apply op_local_update_discrete. - - rewrite -lat_op_join' right_id_L left_id_L. apply auth_update_alloc. - rewrite cmra_comm_L -{2}(right_id_L ε op (to_latT Ut')). - by apply op_local_update_discrete. - Qed. - - Lemma StrongTok_Auth_agree γ st q : - StrongAuth γ st ∗ StrongTok γ q -∗ - ⌜∃ q' strong, st = Some (q', strong) ∧ - if decide (strong = xH) then q = q' else ∃ q'', q' = (q + q'')%Qp⌝. - Proof. - rewrite -embed_sep -own_op. iIntros "oA". - iDestruct (own_valid with "oA") - as %[[[[|INCL]%option_included _]%auth_valid_discrete_2 _] _]; [done|]. - iPureIntro. destruct INCL as [q1 [[q' n] [Eq1 [Eq2 Eq3]]]]. - inversion Eq1. subst q1. exists q', n. split; [done|]. - destruct Eq3 as [[Eq3 Eq4]|[[q'' Le1] Le2%pos_included]%prod_included]. - - inversion Eq3. inversion Eq4. simpl in *. by subst. - - simpl in *. rewrite decide_False. exists q''. by rewrite Le1 frac_op'. - move => ?. by subst n. - Qed. - - Lemma WeakTok_Auth_agree γ st q : - WeakAuth γ st ∗ WeakTok γ q -∗ - ⌜∃ q' weak isStr, st = (isStr, Some $ Cinl (q', weak)) ∧ - if decide (weak = xH) then q = q' else ∃ q'', q' = (q + q'')%Qp⌝. - Proof. - rewrite -embed_sep -own_op. iIntros "oA". - iDestruct (own_valid with "oA") - as %[[_ [[_ INCL]%prod_included VALID]%auth_valid_discrete_2] _]. - iPureIntro. destruct st as [st' st]. simpl in *. - apply option_included in INCL as [|[q1 [qn [Eq1 [Eq2 Eq3]]]]]; [done|]. - subst st. inversion Eq1. subst q1. destruct Eq3 as [Eq3|INCL]. - - exists q, xH, st'. inversion Eq3 as [? ? Eq4| |]. subst. - apply leibniz_equiv_iff in Eq4. by subst. - - destruct VALID as [? ?]. simpl in *. - apply csum_included in INCL as [?|[([??]&[q' weak]&Eq2&?&INCL)|(?&?&?&?)]]; - [by subst qn|..|done]. - subst qn. exists q', weak, st'. split; [done|]. inversion Eq2. subst. - apply prod_included in INCL as [[q'' Eq] INCLs%pos_included]. simpl in *. - rewrite decide_False. - exists q''. by rewrite Eq frac_op'. move => ?. by subst weak. - Qed. - - Lemma StrongAuth_first_tok γ : - StrongAuth γ None ==∗ - StrongAuth γ (Some ((1/2)%Qp, 1%positive)) ∗ StrongTok γ (1/2)%Qp. - Proof. - iIntros "own". rewrite -embed_sep -own_op. - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; simpl; [|by rewrite right_id]. - apply prod_update; simpl; [|done]. apply auth_update_alloc. - rewrite /= -(right_id None op (Some _)). by apply op_local_update_discrete. - Qed. - - Lemma StrongAuth_new_tok γ (q q': frac) n (Hqq' : (q + q')%Qp = 1%Qp): - StrongAuth γ (Some (q,n)) ==∗ - StrongAuth γ (Some ((q + (q'/2)%Qp)%Qp, (n + 1)%positive)) ∗ - StrongTok γ (q'/2)%Qp. - Proof. - iIntros "own". rewrite -embed_sep -own_op. - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; simpl; [|by rewrite right_id]. - apply prod_update; simpl; [|done]. apply auth_update_alloc. - rewrite Pos.add_comm Qp_plus_comm -pos_op_plus /= -frac_op' -pair_op Some_op. - rewrite -{2}(right_id None op (Some ((q' /2)%Qp, _))). - apply op_local_update_discrete => _ /=. split; simpl; [|done]. - apply frac_valid'. rewrite -Hqq' comm -{2}(Qp_div_2 q'). - apply Qcplus_le_mono_l. rewrite -{1}(Qcanon.Qcplus_0_l (q'/2)%Qp). - apply Qcplus_le_mono_r, Qp_ge_0. - Qed. - - Lemma WeakAuth_first_tok γ iS : - WeakAuth γ (iS, None) ==∗ - WeakAuth γ (iS, Some $ Cinl ((1/2)%Qp, 1%positive)) ∗ WeakTok γ (1/2)%Qp. - Proof. - iIntros "own". rewrite -embed_sep -own_op. - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; simpl; [|by rewrite right_id]. - apply prod_update; simpl; [done|]. apply auth_update_alloc. - apply prod_local_update; simpl; [done|]. - rewrite /= -(right_id None op (Some _)). by apply op_local_update_discrete. - Qed. - - Lemma WeakAuth_new_tok γ iS (q q': frac) n (Hqq' : (q + q')%Qp = 1%Qp): - WeakAuth γ (iS, Some (Cinl (q, n))) ==∗ - WeakAuth γ (iS, Some (Cinl ((q + (q'/2)%Qp)%Qp, (n + 1)%positive))) ∗ - WeakTok γ (q'/2)%Qp. - Proof. - iIntros "own". rewrite -embed_sep -own_op. - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; simpl; [|by rewrite right_id]. - apply prod_update; simpl; [done|]. apply auth_update_alloc. - apply prod_local_update; simpl; [done|]. - rewrite Pos.add_comm Qp_plus_comm -pos_op_plus /= - -frac_op' -pair_op -Cinl_op Some_op. - rewrite -{2}(right_id None op (Some $ Cinl ((q' /2)%Qp, _))). - apply op_local_update_discrete => _ /=. split; simpl; [|done]. - apply frac_valid'. rewrite -Hqq' comm -{2}(Qp_div_2 q'). - apply Qcplus_le_mono_l. rewrite -{1}(Qcanon.Qcplus_0_l (q'/2)%Qp). - apply Qcplus_le_mono_r, Qp_ge_0. - Qed. - - Lemma StrongAuth_drop_last γ q: - StrongAuth γ (Some (q,1%positive)) ∗ StrongTok γ q ==∗ - StrongAuth γ None. - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; simpl; [|by rewrite right_id]. - apply prod_update; simpl; [|done]. - apply auth_update_dealloc. rewrite /= -(right_id None op (Some _)). - apply cancel_local_update_unit, _. - Qed. - - Lemma StrongAuth_drop γ q q' n: - StrongAuth γ (Some ((q + q')%Qp,(1 + n)%positive)) ∗ StrongTok γ q' ==∗ - StrongAuth γ (Some (q,n)). - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; [|simpl; by rewrite right_id]. apply prod_update; [|done]. - apply auth_update_dealloc. - rewrite -frac_op' -pos_op_plus /= (cmra_comm_L q) -pair_op Some_op. - by apply (cancel_local_update_unit (Some _)), _. - Qed. - - Lemma WeakAuth_drop_last γ iS q: - WeakAuth γ (iS, Some $ Cinl (q,1%positive)) ∗ WeakTok γ q ==∗ - WeakAuth γ (iS, None). - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; [|by rewrite /= right_id]. apply prod_update; [done|]. - apply auth_update_dealloc. apply prod_local_update; [done|]. - rewrite /= -(right_id None op (Some _)). apply cancel_local_update_unit, _. - Qed. - - Lemma WeakAuth_drop γ iS (q q': frac) n: - WeakAuth γ (iS, Some (Cinl ((q + q')%Qp,(1 + n)%positive))) ∗ - WeakTok γ q' ==∗ - WeakAuth γ (iS, Some (Cinl (q,n))). - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; [|simpl; by rewrite right_id]. apply prod_update; [done|]. - apply auth_update_dealloc. apply prod_local_update; [done|]. - rewrite -frac_op' -pos_op_plus /= (cmra_comm_L q) -pair_op -Cinl_op Some_op. - by apply (cancel_local_update_unit (Some _)), _. - Qed. - - Lemma WeakAuth_strong γ iS st q : - WeakAuth γ (iS, st) ∗ agown γ (awk_n ((Some q, ε))) -∗ ∃ q', ⌜iS = Some q'⌝. - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iDestruct (own_valid with "own") as %[[_ [VAL _]%auth_valid_discrete_2] _]. - iPureIntro. move : VAL => /prod_included /= [/option_included [//|[?[? [?[??]]]]] _]. - subst iS. by eexists. - Qed. - - Lemma WeakAuth_valid γ iS st : - WeakAuth γ (iS, st) -∗ ⌜st ≠ Some CsumBot⌝. - Proof. - iIntros "own". - iDestruct (@own_valid _ arcUR with "own") as %[[_ [_ [_ VAL]]%auth_valid_discrete] _]. - simpl in VAL. iPureIntro. by destruct st as [[| |]|]. - Qed. - - Lemma WeakAuth_drop_strong γ st: - WeakAuth γ (Some 1%Qp, st) ∗ agown γ (awk_n ((Some 1%Qp, ε))) ==∗ - WeakAuth γ (None, st). - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; [|by rewrite /= right_id]. apply prod_update; [done|]. - apply auth_update_dealloc. apply prod_local_update; [|done]. - rewrite /= -{1}(right_id None op (Some _)). - by apply (cancel_local_update_unit (Some _)), _. - Qed. - - Lemma StrWkTok_exclusive γ q : - agown γ (awk_n ((Some 1%Qp, ε))) ∗ agown γ (awk_n ((Some q, ε))) -∗ False. - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iDestruct (@own_valid _ arcUR with "own") as %[[_ VAL] _]. simpl in VAL. - iPureIntro. move : VAL. rewrite -auth_frag_op pair_op -Some_op frac_op'. - move => /auth_valid_discrete /= [/= ? _]. - have Lt: (1%Qp < (1%Qp + q)%Qp)%Qc. apply Qp_lt_sum. by eexists. - apply (irreflexive_eq (R:= Qclt) 1%Qp 1%Qp); [done|]. - eapply Qclt_le_trans; [apply Lt|done]. - Qed. - - Lemma StrMoves_full_exclusive γ q Mt' : - (∃ Mt, StrMoves γ 1%Qp Mt) -∗ StrMoves γ q Mt' -∗ False. - Proof. - iDestruct 1 as (Mt) "SM". iIntros "SM'". - iDestruct (StrMoves_agree with "[$SM $SM']") as %?. subst Mt'. - iDestruct (StrMoves_fractional with "[$SM $SM']") as "SM". - iDestruct (@own_valid _ arcUR with "SM") as %[_ [[[[VAL _] _] _] _]]. - iPureIntro. simpl in VAL. - have Lt: (1%Qp < (1%Qp + q)%Qp)%Qc. apply Qp_lt_sum. by eexists. - apply (irreflexive_eq (R:= Qclt) 1%Qp 1%Qp); [done|]. - eapply Qclt_le_trans; [apply Lt|done]. - Qed. - - Lemma WeakAuth_new_lock γ iS q: - WeakAuth γ (iS, None) ==∗ - WeakAuth γ (iS, Some $ Cinr (Excl (), to_agree q)) ∗ WkLock γ q. - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; [|by rewrite /= right_id]. apply prod_update; [done|]. simpl. - apply auth_update_alloc. apply prod_local_update; simpl; [done|]. - rewrite -(right_id None op (Some _)). - by apply op_local_update_discrete. - Qed. - - Lemma WeakAuth_lock_agree γ iS st q: - WeakAuth γ (iS, st) ∗ WkLock γ q -∗ - ⌜st ≡ Some (Cinr (Excl tt, to_agree q))⌝. - Proof. - rewrite -embed_sep -own_op. iIntros "own". - iDestruct (@own_valid _ arcUR with "own") - as %[[_ [[_ [?|INCL]%option_included]%prod_included [_ VAL]]%auth_valid_discrete_2] _]; - [done|]. iPureIntro. - destruct INCL as (x & y & Eq1 & Eq2 & INCL). simpl in *. inversion Eq1. - subst x st. destruct INCL as [Eq|INCL]. - - inversion Eq as [|? b Eq2 |]. subst. by rewrite -Eq2. - - apply csum_included in INCL as [?|[(?&?&?&?)|(?&[u v]&Eq&?&[IN1 IN2]%prod_included)]]; - [by subst y|done|..]. - subst. inversion Eq. clear Eq. subst. - move : VAL => [VAL1 /to_agree_uninj [? VAL2]]. destruct u as [[]|]; [|done]. - simpl in *. move : IN2. rewrite -VAL2. move => /to_agree_included <- //. - Qed. - - Lemma WeakAuth_unlock γ iS st q : - WeakAuth γ (iS, st) ∗ WkLock γ q ==∗ WeakAuth γ (iS, None). - Proof. - iIntros "own". iDestruct (WeakAuth_lock_agree with "own") as %Eq. - rewrite -embed_sep -own_op. - iMod (@own_update _ arcUR with "own") as "$"; [|done]. - apply prod_update; [|by rewrite /= right_id]. apply prod_update; [done|]. simpl. - rewrite Eq. apply auth_update_dealloc. apply prod_local_update; [done|]. - rewrite /= -{1}(right_id None op (Some _)). - apply (cancel_local_update_unit (Some _)), _. - Qed. -End ArcGhost. Section ArcInv. (* P1 is the thing that is shared by strong reference owners (in practice, @@ -934,11 +300,14 @@ Section arc. destruct st as [[|] [[[]| |]|]]; simpl; try done. solve_proper. Qed. - (* TODO: port to local assertion iff Global Instance arc_inv_proper : - Proper (pointwise_relation _ (≡) ==> (≡) ==> eq ==> eq ==> (≡)) + Proper (pointwise_relation _ (≡) ==> (≡) ==> eq ==> eq ==> eq ==> eq ==> (≡)) arc_inv. - Proof. solve_proper. Qed. *) + Proof. + move => ??????????????????. subst. apply bi.or_proper; [done|]. + apply bi.sep_proper; [done|]. + apply bi.sep_proper; apply bi.exist_proper => V. + Abort. Global Instance is_arc_contractive n : Proper (pointwise_relation _ (dist_later n) ==> dist_later n ==> diff --git a/theories/lang/arc_cmra.v b/theories/lang/arc_cmra.v new file mode 100644 index 0000000000000000000000000000000000000000..ff20954a9b5b5272ad38ca5ee9338d2d7bf78509 --- /dev/null +++ b/theories/lang/arc_cmra.v @@ -0,0 +1,643 @@ +From Coq.QArith Require Import Qcanon. +From iris.base_logic.lib Require Import invariants. +From iris.proofmode Require Import tactics. +From iris.bi Require Import fractional. +From iris.algebra Require Import excl csum frac auth agree. +From lrust.lang Require Import notation. +From gpfsl.gps Require Import middleware protocols. +Set Default Proof Using "Type". + +(* Lattice of sets with subseteq *) +Program Canonical Structure gset_Lat (A: Type) `{Countable A} := + Make_Lat (gset A) (≡) subseteq union intersection + _ _ _ _ _ _ _ _ _ _ _ _ _. +Next Obligation. move => ???. by apply union_subseteq_l. Qed. +Next Obligation. move => ???. by apply union_subseteq_r. Qed. +Next Obligation. move => ???. by apply union_least. Qed. +Next Obligation. move => ???. by apply intersection_subseteq_l. Qed. +Next Obligation. move => ???. by apply intersection_subseteq_r. Qed. +Next Obligation. move => ??????. by apply intersection_greatest. Qed. + +Instance gset_Lat_bot `{Countable A} : LatBottom (∅ : gset_Lat A). +Proof. done. Qed. + +(** The CMRAs we need. *) + +(* This cmra tracks what the arc must have done by itself when it is the unique clone. + + Self here means that the cmra is updated when the caller moves its own counter, + e.g. the strong arc modifying the strong counter, or the weak arc modifying + the weak counter. + For the strong counter, it tracks the actions: moving 1 to 0 + (the last release/drop), and 1 to 2 (the unique clone). + For the weak counter, it tracks the self actions: moving 1 to -1 (locking), + moving 1 to 0 (the last drop), and 1 to 2 (the unique clone). + + The authority should only be updated when having full fraction, + i.e. the caller being unique. A persistent certificate is issued when the + authority is updated. A fraction of the authority must have seen all certificates. *) +Definition move_selfUR := + prodUR (authUR (optionUR (prodR fracR (agreeR (latC (gset_Lat time)))))) + (authUR (latUR (gset_Lat time))). + +(* This cmra tracks what the arc has asked the other to do, e.g., the weak arc + asks the strong counter to increment when upgrading, or the strong arc asks + the weak counter to increment when downgrading. + + The authority part is owned by the caller, and issue a certificate for + the callee to store in its update. There can be multiple authorities, + each is owned by one caller. A fraction of the authority can issue certificates, + while only the full fraction authority is guaranteed to have seen all certificates. *) +Definition move_otherUR := + prodUR (authUR (optionUR (prodR fracR (latR (gset_Lat time))))) + (authUR (latUR (gset_Lat time))). + +(* This cmra tracks states of the weak counter: + - (None, None) : no strong or weak arc, v = 0. + - (None, Some Cinl (q,n)) : no strong arc, n weak arcs that use q permission, + v = n. + - (None, Some Cinr q) : no strong arc, no weak arc, the weak counter is locked + with a payload of q from a strong arc, v = -1. This state is IMPOSSIBLE. + - (Some 1, None) : some strong arcs, no weak arcs, v = 1. + - (Some 1, Some Cinl (q,n)) : some strong arcs, n weak arcs that use q, v = S n. + - (Some 1, Some Cinr q) : some strong arcs, no weak arc, the weak counter is + locked with a payload of q from a strong arc, v = -1. +*) + +Definition weak_stUR := + prodUR (optionUR fracR) + (optionUR (csumR (prodR fracR positiveR) (prodR (exclR unitC) (agreeR fracC)))). + +(* This cmra tracks states of the strong counter: + - None: no strong arc, v = 0. + - Some (q,n): n strong arcs that took out q, v = n. *) +Definition strong_stUR := + optionUR (prodR fracR positiveR). + +(* The final cmra has 5 components + (strong arc states, weak arc states), + (strong arc self, strong arc downgrade), + (weak arc upgrade) *) +Definition arcUR := + prodUR (prodUR (authUR strong_stUR) (authUR weak_stUR)) + (prodUR (prodUR move_selfUR move_otherUR) move_otherUR). + +Class arcG Σ := { + ArcStG :> inG Σ arcUR; + ArcPrt_gpsG :> gpsG Σ unitProtocol; +}. +Definition arcΣ : gFunctors := #[GFunctor arcUR; gpsΣ unitProtocol]. +Instance subG_arcΣ {Σ} : subG arcΣ Σ → arcG Σ. +Proof. solve_inG. Qed. + +Definition Z_of_arcweak_st (st : weak_stUR) : Z := + match st with + | (None, None) => 0 + | (Some _, None) => 1 + | (None, Some (Cinl (_, n))) => Zpos n + | (Some _, Some (Cinl (_, n))) => Zpos n +1 + | (_, Some _) => -1 + end. + +Definition Z_of_arcstrong_st (st : strong_stUR) : Z := + match st with + | None => 0 + | Some (_, n) => Zpos n + end. + + +Lemma strong_stUR_value st: 0 ≤ Z_of_arcstrong_st st. +Proof. destruct st as [[]|]; simpl; lia. Qed. + +Lemma weak_stUR_value st: -1 ≤ Z_of_arcweak_st st. +Proof. destruct st as [[|] [[[]| |]|]]; simpl; lia. Qed. + +Notation agown γ st := (⎡ own γ (st : arcUR) ⎤ : vProp _)%I. +Notation awk_n st := ((ε, ◯ (st : weak_stUR)), ε). + +Section ArcGhost. + Context `{inG Σ arcUR}. + Local Notation vProp := (vProp Σ). + Implicit Types (Mt Ut Dt: gset time). + + Definition StrongAuth γ (st : strong_stUR) := + agown γ ((● st, ε), ε). + Definition StrongTok γ q := + agown γ ((◯ Some (q, xH), ε), ε). + Definition StrongMoveAuth γ Mt := + agown γ (ε, (((● Some (1%Qp, to_agree $ to_latT Mt), ● to_latT Mt) : move_selfUR, ε), ε)). + Definition StrMoves γ (q: frac) Mt := + agown γ (ε, (((◯ Some (q, to_agree $ to_latT Mt), ε) : move_selfUR, ε), ε)). + Definition StrongDownAuth γ Dt := + agown γ (ε, ((ε, (● Some (1%Qp, to_latT Dt), ● to_latT Dt) : move_otherUR), ε)). + Definition StrDowns γ (q: frac) Dt := + agown γ (ε, ((ε, (◯ Some (q, to_latT Dt), ε) : move_otherUR), ε)). + Definition StrMoveCertS γ Mt : vProp := + agown γ (ε, (((ε, ◯ to_latT Mt) : move_selfUR, ε), ε)). + Definition StrDownCertS γ Mt : vProp := + agown γ (ε, ((ε, (ε, ◯ to_latT Mt) : move_otherUR), ε)). + Definition StrMoveCert γ t := StrMoveCertS γ {[t : time]}. + Definition StrDownCert γ t := StrDownCertS γ {[t : time]}. + + Definition WeakAuth γ (st : weak_stUR) := + agown γ ((ε, ● st), ε). + Definition WeakTok γ q := + agown γ ((ε, ◯ (ε, Some (Cinl (q, xH)))), ε). + Definition WeakUpAuth γ Ut := + agown γ (ε, (ε, (● Some (1%Qp, to_latT Ut), ● to_latT Ut) : move_otherUR)). + Definition WkUps γ (q: frac) Ut := + agown γ (ε, (ε, (◯ Some (q, to_latT Ut), ε) : move_otherUR)). + Definition WkUpCertS γ Mt := + agown γ (ε, (ε, (ε, ◯ to_latT Mt) : move_otherUR)). + Definition WkUpCert γ t := WkUpCertS γ {[t : time]}. + Definition WkLock γ q := + agown γ (ε, ◯ (ε, Some $ Cinr (Excl(), to_agree q)),ε) . + + Global Instance StrMoveCertS_persistent γ Mt : Persistent (StrMoveCertS γ Mt). + Proof. apply embed_persistent, own_core_persistent, pair_core_id; by apply _. Qed. + Global Instance StrDownCertS_persistent γ Mt : Persistent (StrDownCertS γ Mt). + Proof. apply embed_persistent, own_core_persistent, pair_core_id; by apply _. Qed. + Global Instance WkUpCertS_persistent γ Mt : Persistent (WkUpCertS γ Mt). + Proof. apply embed_persistent, own_core_persistent, pair_core_id; by apply _. Qed. + Global Instance StrMoves_fractional γ Mt : Fractional (λ q, StrMoves γ q Mt). + Proof. + rewrite /Fractional => p q. rewrite -embed_sep -own_op. + apply embed_proper, own.own_proper. + apply pair_proper; [done|]. do 3 (apply pair_proper; [|done]). simpl. + by rewrite -auth_frag_op -Some_op pair_op frac_op' agree_idemp. + Qed. + Global Instance StrMoves_asfractional γ q Mt : + AsFractional (StrMoves γ q Mt) (λ q, StrMoves γ q Mt) q. + Proof. split. done. apply _. Qed. + Global Instance StrDowns_fractional γ Dt : Fractional (λ q, StrDowns γ q Dt). + Proof. + rewrite /Fractional => p q. rewrite -embed_sep -own_op. + apply embed_proper, own.own_proper. + apply pair_proper; [done|]. apply pair_proper; [|done]. + rewrite /=. setoid_rewrite pair_op. apply pair_proper; [done|]. + rewrite pair_op. apply pair_proper; [|done]. + by rewrite -auth_frag_op -Some_op pair_op frac_op' lat_op_join' lat_join_idem_L. + Qed. + Global Instance StrDowns_asfractional γ q Dt : + AsFractional (StrDowns γ q Dt) (λ q, StrDowns γ q Dt) q. + Proof. split. done. apply _. Qed. + Global Instance WkUps_fractional γ Ut : Fractional (λ q, WkUps γ q Ut). + Proof. + rewrite /Fractional => p q. rewrite -embed_sep -own_op. + apply embed_proper, own.own_proper. + do 2 (apply pair_proper; [done|]). + rewrite /=. setoid_rewrite pair_op. apply pair_proper; [|done]. + by rewrite -auth_frag_op -Some_op pair_op frac_op' lat_op_join' lat_join_idem_L. + Qed. + Global Instance WkUps_asfractional γ q Ut : + AsFractional (WkUps γ q Ut) (λ q, WkUps γ q Ut) q. + Proof. split. done. apply _. Qed. + + (* move_self *) + Local Notation moveSAuth Mt + := ((● Some (1%Qp, to_agree $ to_latT Mt), ● to_latT Mt) : move_selfUR). + Local Notation moveSMain q Mt + := ((◯ Some (q, to_agree $ to_latT Mt), ε) : move_selfUR). + Local Notation certS Mt + := ((ε, ◯ to_latT Mt) : move_selfUR). + + Lemma arc_ghost_move_self_main_valid Mt1 Mt2 q: + ✓ (moveSAuth Mt1 ⋅ moveSMain q Mt2) → Mt2 = Mt1. + Proof. + rewrite pair_op right_id_L. + move => [/= /auth_valid_discrete_2 [/Some_included + [[_ /= /to_agree_inj /to_latT_inj /leibniz_equiv_iff //]| + /prod_included[_ /to_agree_included /to_latT_inj /leibniz_equiv_iff //]]_]_]. + Qed. + + Lemma arc_ghost_move_self_cert_valid Mt1 Mt2: + ✓ (moveSAuth Mt1 ⋅ certS Mt2) → Mt2 ⊆ Mt1. + Proof. rewrite pair_op => [[_ /auth_valid_discrete_2 [/latT_included // _]]]. Qed. + + Lemma StrongMoveAuth_agree γ Mt q Mt': + StrongMoveAuth γ Mt ∗ StrMoves γ q Mt' -∗ ⌜Mt = Mt'⌝. + Proof. + rewrite -embed_sep -own_op. + iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. + move : VALID => [/=_ [/= ]]. rewrite pair_op. + move => [/= /arc_ghost_move_self_main_valid //]. + Qed. + + Lemma StrMoves_agree γ Mt Mt' q q': + StrMoves γ q Mt ∗ StrMoves γ q' Mt' -∗ ⌜Mt = Mt'⌝. + Proof. + rewrite -embed_sep -own_op. + iIntros "own". iDestruct (own_valid with "own") as %VAL. iPureIntro. + move : VAL => [/=_ [/= [[VAL _]_]_]]. move :VAL. + rewrite /= -auth_frag_op -Some_op pair_op auth_valid_discrete /= Some_valid. + move => [_ /agree_op_inv' /to_latT_inj /leibniz_equiv_iff // ]. + Qed. + + Lemma StrongMoveAuth_Cert_include γ Mt Mt': + StrongMoveAuth γ Mt ∗ StrMoveCertS γ Mt' -∗ ⌜Mt' ⊆ Mt⌝. + Proof. + rewrite -embed_sep -own_op. + iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. + move :VALID => [/= _ [/= ]]. rewrite pair_op. + move => [/= /arc_ghost_move_self_cert_valid //]. + Qed. + + Lemma StrMoves_update γ Mt Mt': + StrongMoveAuth γ Mt ∗ StrMoves γ 1%Qp Mt ==∗ + StrongMoveAuth γ (Mt ∪ Mt') ∗ StrMoves γ 1%Qp (Mt ∪ Mt') ∗ StrMoveCertS γ Mt'. + Proof. + rewrite -3!embed_sep -3!own_op. iIntros "own". + iMod (own_update with "own") as "$"; [|done]. + apply prod_update; [done|]. + apply prod_update; [|rewrite /= left_id right_id //]. + setoid_rewrite pair_op. rewrite /=. + apply prod_update; [|rewrite /= left_id right_id //]. + rewrite /= 2!pair_op /= 2!right_id left_id. + apply prod_update; simpl. + - by apply auth_update, option_local_update, exclusive_local_update. + - apply auth_update_alloc. + rewrite -(right_id_L ε op (to_latT Mt')) -lat_op_join' cmra_comm. + by apply op_local_update_discrete. + Qed. + + (* move_other *) + Local Notation moveOAuth Mt := ((● Some (1%Qp, to_latT Mt), ● to_latT Mt) : move_otherUR). + Local Notation moveOMain q Mt := ((◯ Some (q, to_latT Mt), ε) : move_otherUR). + Local Notation certO Mt := ((ε, ◯ to_latT Mt) : move_otherUR). + + Lemma arc_ghost_move_other_main_valid Mt1 Mt2: + ✓ (moveOAuth Mt1 ⋅ moveOMain 1%Qp Mt2) → Mt2 = Mt1. + Proof. + rewrite pair_op. + move => [/= /auth_valid_discrete_2 [/Some_included + [[/= _ /to_latT_inj /leibniz_equiv_iff //]| + /prod_included [/= /frac_included /= // _]]]]. + Qed. + + Lemma arc_ghost_move_other_cert_valid Mt1 Mt2: + ✓ (moveOAuth Mt1 ⋅ certO Mt2) → Mt2 ⊆ Mt1. + Proof. + rewrite pair_op right_id_L. + move => [/= _ /auth_valid_discrete_2 [/latT_included // ]]. + Qed. + + Lemma StrongDownAuth_agree γ Dt Dt': + StrongDownAuth γ Dt ∗ StrDowns γ 1%Qp Dt' -∗ ⌜Dt = Dt'⌝. + Proof. + rewrite -embed_sep -own_op. + iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. + move : VALID => [/=_ [/= [/= _ /arc_ghost_move_other_main_valid //]]]. + Qed. + + Lemma StrongDownAuth_Cert_include γ Dt Dt': + StrongDownAuth γ Dt ∗ StrDownCertS γ Dt' -∗ ⌜Dt' ⊆ Dt⌝. + Proof. + rewrite -embed_sep -own_op. + iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. + move :VALID => [/= _ [/= [/= _ /arc_ghost_move_other_cert_valid //]]]. + Qed. + + Lemma StrDowns_forget γ q q' Dt Dt': + StrDowns γ (q + q')%Qp (Dt ∪ Dt') ≡ + (StrDowns γ q (Dt ∪ Dt') ∗ StrDowns γ q' Dt')%I. + Proof. + rewrite -embed_sep -own_op. apply embed_proper, own.own_proper. + do 2 (apply pair_proper; [done|]; apply pair_proper; [|done]). + simpl. rewrite -auth_frag_op -Some_op pair_op -frac_op' lat_op_join'. + rewrite (lat_le_join_l_L (Dt ∪ Dt') Dt'); [done|solve_lat]. + Qed. + + Lemma WeakUpAuth_agree γ Ut Ut': + WeakUpAuth γ Ut ∗ WkUps γ 1%Qp Ut' -∗ ⌜Ut = Ut'⌝. + Proof. + rewrite -embed_sep -own_op. + iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. + move : VALID => [/=_ [/= _ /arc_ghost_move_other_main_valid //]]. + Qed. + + Lemma WeakUpAuth_Cert_include γ Ut Ut': + WeakUpAuth γ Ut ∗ WkUpCertS γ Ut' -∗ ⌜Ut' ⊆ Ut⌝. + Proof. + rewrite -embed_sep -own_op. + iIntros "own". iDestruct (own_valid with "own") as %VALID. iPureIntro. + move :VALID => [/= _ [/= _ /arc_ghost_move_other_cert_valid //]]. + Qed. + + Lemma WkUps_forget γ q q' Ut Ut': + WkUps γ (q + q')%Qp (Ut ∪ Ut') ≡ + (WkUps γ q (Ut ∪ Ut') ∗ WkUps γ q' Ut')%I. + Proof. + rewrite -embed_sep -own_op. apply embed_proper, own.own_proper. + do 2 (apply pair_proper; [done|]). apply pair_proper; [|done]. simpl. + rewrite -auth_frag_op -Some_op pair_op -frac_op' lat_op_join'. + rewrite (lat_le_join_l_L (Ut ∪ Ut') Ut'); [done|solve_lat]. + Qed. + + Lemma StrDowns_join γ Dt Dt' q q' : + StrDowns γ (q + q')%Qp (Dt ∪ Dt') ≡ + (StrDowns γ q Dt ∗ StrDowns γ q' Dt')%I. + Proof. + rewrite -embed_sep -own_op. apply embed_proper, own.own_proper. + do 2 (apply pair_proper; [done|]; apply pair_proper; [|done]). + simpl. by rewrite -auth_frag_op -Some_op pair_op -frac_op' lat_op_join'. + Qed. + + Lemma StrDowns_update γ Dt1 Dt2 Dt' q : + StrongDownAuth γ Dt1 ∗ StrDowns γ q Dt2 ==∗ + StrongDownAuth γ (Dt1 ⊔ Dt') ∗ StrDowns γ q (Dt2 ⊔ Dt') ∗ StrDownCertS γ Dt'. + Proof. + rewrite -3!embed_sep -3!own_op. iIntros "own". + iMod (own_update with "own") as "$"; [|done]. + apply prod_update; [done|]. simpl. + apply prod_update; [|rewrite /= !right_id //]. + setoid_rewrite pair_op. rewrite /=. + apply prod_update; [rewrite /= !right_id //|]. + rewrite /= 2!pair_op /= 2!right_id_L left_id_L. rewrite -2!lat_op_join'. + apply prod_update; simpl. + - apply auth_update, option_local_update, prod_local_update_2. + rewrite (cmra_comm_L (to_latT Dt1)) (cmra_comm_L (to_latT Dt2)). + by apply op_local_update_discrete. + - apply auth_update_alloc. + rewrite cmra_comm_L -{2}(right_id_L ε op (to_latT Dt')). + by apply op_local_update_discrete. + Qed. + + Lemma WkUps_join γ Ut Ut' q q' : + WkUps γ (q + q')%Qp (Ut ∪ Ut') ≡ + (WkUps γ q Ut ∗ WkUps γ q' Ut')%I. + Proof. + rewrite -embed_sep -own_op. apply embed_proper, own.own_proper. + by do 3 (apply pair_proper; [done|]). + Qed. + + Lemma WkUps_full_exclusive γ q Ut' : + (∃ Ut, WkUps γ 1%Qp Ut) -∗ WkUps γ q Ut' -∗ False. + Proof. + iDestruct 1 as (Ut) "WU". iIntros "WU'". + iDestruct (WkUps_join with "[$WU $WU']") as "WU". + iDestruct (@own_valid _ arcUR with "WU") + as %[_ [_ [[VAL _]%auth_valid_discrete _]]]. + iPureIntro. simpl in VAL. + have Lt: (1%Qp < (1%Qp + q)%Qp)%Qc. apply Qp_lt_sum. by eexists. + apply (irreflexive_eq (R:= Qclt) 1%Qp 1%Qp); [done|]. + eapply Qclt_le_trans; [apply Lt|done]. + Qed. + + Lemma WkUps_update γ Ut1 Ut2 Ut' q : + WeakUpAuth γ Ut1 ∗ WkUps γ q Ut2 ==∗ + WeakUpAuth γ (Ut1 ⊔ Ut') ∗ WkUps γ q (Ut2 ⊔ Ut') ∗ WkUpCertS γ Ut'. + Proof. + rewrite -3!embed_sep -3!own_op. iIntros "own". + iMod (own_update with "own") as "$"; [|done]. + apply prod_update; [done|]. simpl. + apply prod_update; [rewrite /= !right_id //|]. + apply prod_update; rewrite /=. + - apply auth_update, option_local_update, prod_local_update_2. + rewrite -2!lat_op_join' (cmra_comm_L (to_latT Ut1)) (cmra_comm_L (to_latT Ut2)). + by apply op_local_update_discrete. + - rewrite -lat_op_join' right_id_L left_id_L. apply auth_update_alloc. + rewrite cmra_comm_L -{2}(right_id_L ε op (to_latT Ut')). + by apply op_local_update_discrete. + Qed. + + Lemma StrongTok_Auth_agree γ st q : + StrongAuth γ st ∗ StrongTok γ q -∗ + ⌜∃ q' strong, st = Some (q', strong) ∧ + if decide (strong = xH) then q = q' else ∃ q'', q' = (q + q'')%Qp⌝. + Proof. + rewrite -embed_sep -own_op. iIntros "oA". + iDestruct (own_valid with "oA") + as %[[[[|INCL]%option_included _]%auth_valid_discrete_2 _] _]; [done|]. + iPureIntro. destruct INCL as [q1 [[q' n] [Eq1 [Eq2 Eq3]]]]. + inversion Eq1. subst q1. exists q', n. split; [done|]. + destruct Eq3 as [[Eq3 Eq4]|[[q'' Le1] Le2%pos_included]%prod_included]. + - inversion Eq3. inversion Eq4. simpl in *. by subst. + - simpl in *. rewrite decide_False. exists q''. by rewrite Le1 frac_op'. + move => ?. by subst n. + Qed. + + Lemma WeakTok_Auth_agree γ st q : + WeakAuth γ st ∗ WeakTok γ q -∗ + ⌜∃ q' weak isStr, st = (isStr, Some $ Cinl (q', weak)) ∧ + if decide (weak = xH) then q = q' else ∃ q'', q' = (q + q'')%Qp⌝. + Proof. + rewrite -embed_sep -own_op. iIntros "oA". + iDestruct (own_valid with "oA") + as %[[_ [[_ INCL]%prod_included VALID]%auth_valid_discrete_2] _]. + iPureIntro. destruct st as [st' st]. simpl in *. + apply option_included in INCL as [|[q1 [qn [Eq1 [Eq2 Eq3]]]]]; [done|]. + subst st. inversion Eq1. subst q1. destruct Eq3 as [Eq3|INCL]. + - exists q, xH, st'. inversion Eq3 as [? ? Eq4| |]. subst. + apply leibniz_equiv_iff in Eq4. by subst. + - destruct VALID as [? ?]. simpl in *. + apply csum_included in INCL as [?|[([??]&[q' weak]&Eq2&?&INCL)|(?&?&?&?)]]; + [by subst qn|..|done]. + subst qn. exists q', weak, st'. split; [done|]. inversion Eq2. subst. + apply prod_included in INCL as [[q'' Eq] INCLs%pos_included]. simpl in *. + rewrite decide_False. + exists q''. by rewrite Eq frac_op'. move => ?. by subst weak. + Qed. + + Lemma StrongAuth_first_tok γ : + StrongAuth γ None ==∗ + StrongAuth γ (Some ((1/2)%Qp, 1%positive)) ∗ StrongTok γ (1/2)%Qp. + Proof. + iIntros "own". rewrite -embed_sep -own_op. + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; simpl; [|by rewrite right_id]. + apply prod_update; simpl; [|done]. apply auth_update_alloc. + rewrite /= -(right_id None op (Some _)). by apply op_local_update_discrete. + Qed. + + Lemma StrongAuth_new_tok γ (q q': frac) n (Hqq' : (q + q')%Qp = 1%Qp): + StrongAuth γ (Some (q,n)) ==∗ + StrongAuth γ (Some ((q + (q'/2)%Qp)%Qp, (n + 1)%positive)) ∗ + StrongTok γ (q'/2)%Qp. + Proof. + iIntros "own". rewrite -embed_sep -own_op. + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; simpl; [|by rewrite right_id]. + apply prod_update; simpl; [|done]. apply auth_update_alloc. + rewrite Pos.add_comm Qp_plus_comm -pos_op_plus /= -frac_op' -pair_op Some_op. + rewrite -{2}(right_id None op (Some ((q' /2)%Qp, _))). + apply op_local_update_discrete => _ /=. split; simpl; [|done]. + apply frac_valid'. rewrite -Hqq' comm -{2}(Qp_div_2 q'). + apply Qcplus_le_mono_l. rewrite -{1}(Qcanon.Qcplus_0_l (q'/2)%Qp). + apply Qcplus_le_mono_r, Qp_ge_0. + Qed. + + Lemma WeakAuth_first_tok γ iS : + WeakAuth γ (iS, None) ==∗ + WeakAuth γ (iS, Some $ Cinl ((1/2)%Qp, 1%positive)) ∗ WeakTok γ (1/2)%Qp. + Proof. + iIntros "own". rewrite -embed_sep -own_op. + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; simpl; [|by rewrite right_id]. + apply prod_update; simpl; [done|]. apply auth_update_alloc. + apply prod_local_update; simpl; [done|]. + rewrite /= -(right_id None op (Some _)). by apply op_local_update_discrete. + Qed. + + Lemma WeakAuth_new_tok γ iS (q q': frac) n (Hqq' : (q + q')%Qp = 1%Qp): + WeakAuth γ (iS, Some (Cinl (q, n))) ==∗ + WeakAuth γ (iS, Some (Cinl ((q + (q'/2)%Qp)%Qp, (n + 1)%positive))) ∗ + WeakTok γ (q'/2)%Qp. + Proof. + iIntros "own". rewrite -embed_sep -own_op. + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; simpl; [|by rewrite right_id]. + apply prod_update; simpl; [done|]. apply auth_update_alloc. + apply prod_local_update; simpl; [done|]. + rewrite Pos.add_comm Qp_plus_comm -pos_op_plus /= + -frac_op' -pair_op -Cinl_op Some_op. + rewrite -{2}(right_id None op (Some $ Cinl ((q' /2)%Qp, _))). + apply op_local_update_discrete => _ /=. split; simpl; [|done]. + apply frac_valid'. rewrite -Hqq' comm -{2}(Qp_div_2 q'). + apply Qcplus_le_mono_l. rewrite -{1}(Qcanon.Qcplus_0_l (q'/2)%Qp). + apply Qcplus_le_mono_r, Qp_ge_0. + Qed. + + Lemma StrongAuth_drop_last γ q: + StrongAuth γ (Some (q,1%positive)) ∗ StrongTok γ q ==∗ + StrongAuth γ None. + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; simpl; [|by rewrite right_id]. + apply prod_update; simpl; [|done]. + apply auth_update_dealloc. rewrite /= -(right_id None op (Some _)). + apply cancel_local_update_unit, _. + Qed. + + Lemma StrongAuth_drop γ q q' n: + StrongAuth γ (Some ((q + q')%Qp,(1 + n)%positive)) ∗ StrongTok γ q' ==∗ + StrongAuth γ (Some (q,n)). + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; [|simpl; by rewrite right_id]. apply prod_update; [|done]. + apply auth_update_dealloc. + rewrite -frac_op' -pos_op_plus /= (cmra_comm_L q) -pair_op Some_op. + by apply (cancel_local_update_unit (Some _)), _. + Qed. + + Lemma WeakAuth_drop_last γ iS q: + WeakAuth γ (iS, Some $ Cinl (q,1%positive)) ∗ WeakTok γ q ==∗ + WeakAuth γ (iS, None). + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; [|by rewrite /= right_id]. apply prod_update; [done|]. + apply auth_update_dealloc. apply prod_local_update; [done|]. + rewrite /= -(right_id None op (Some _)). apply cancel_local_update_unit, _. + Qed. + + Lemma WeakAuth_drop γ iS (q q': frac) n: + WeakAuth γ (iS, Some (Cinl ((q + q')%Qp,(1 + n)%positive))) ∗ + WeakTok γ q' ==∗ + WeakAuth γ (iS, Some (Cinl (q,n))). + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; [|simpl; by rewrite right_id]. apply prod_update; [done|]. + apply auth_update_dealloc. apply prod_local_update; [done|]. + rewrite -frac_op' -pos_op_plus /= (cmra_comm_L q) -pair_op -Cinl_op Some_op. + by apply (cancel_local_update_unit (Some _)), _. + Qed. + + Lemma WeakAuth_strong γ iS st q : + WeakAuth γ (iS, st) ∗ agown γ (awk_n ((Some q, ε))) -∗ ∃ q', ⌜iS = Some q'⌝. + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iDestruct (own_valid with "own") as %[[_ [VAL _]%auth_valid_discrete_2] _]. + iPureIntro. move : VAL => /prod_included /= [/option_included [//|[?[? [?[??]]]]] _]. + subst iS. by eexists. + Qed. + + Lemma WeakAuth_valid γ iS st : + WeakAuth γ (iS, st) -∗ ⌜st ≠ Some CsumBot⌝. + Proof. + iIntros "own". + iDestruct (@own_valid _ arcUR with "own") as %[[_ [_ [_ VAL]]%auth_valid_discrete] _]. + simpl in VAL. iPureIntro. by destruct st as [[| |]|]. + Qed. + + Lemma WeakAuth_drop_strong γ st: + WeakAuth γ (Some 1%Qp, st) ∗ agown γ (awk_n ((Some 1%Qp, ε))) ==∗ + WeakAuth γ (None, st). + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; [|by rewrite /= right_id]. apply prod_update; [done|]. + apply auth_update_dealloc. apply prod_local_update; [|done]. + rewrite /= -{1}(right_id None op (Some _)). + by apply (cancel_local_update_unit (Some _)), _. + Qed. + + Lemma StrWkTok_exclusive γ q : + agown γ (awk_n ((Some 1%Qp, ε))) ∗ agown γ (awk_n ((Some q, ε))) -∗ False. + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iDestruct (@own_valid _ arcUR with "own") as %[[_ VAL] _]. simpl in VAL. + iPureIntro. move : VAL. rewrite -auth_frag_op pair_op -Some_op frac_op'. + move => /auth_valid_discrete /= [/= ? _]. + have Lt: (1%Qp < (1%Qp + q)%Qp)%Qc. apply Qp_lt_sum. by eexists. + apply (irreflexive_eq (R:= Qclt) 1%Qp 1%Qp); [done|]. + eapply Qclt_le_trans; [apply Lt|done]. + Qed. + + Lemma StrMoves_full_exclusive γ q Mt' : + (∃ Mt, StrMoves γ 1%Qp Mt) -∗ StrMoves γ q Mt' -∗ False. + Proof. + iDestruct 1 as (Mt) "SM". iIntros "SM'". + iDestruct (StrMoves_agree with "[$SM $SM']") as %?. subst Mt'. + iDestruct (StrMoves_fractional with "[$SM $SM']") as "SM". + iDestruct (@own_valid _ arcUR with "SM") as %[_ [[[[VAL _] _] _] _]]. + iPureIntro. simpl in VAL. + have Lt: (1%Qp < (1%Qp + q)%Qp)%Qc. apply Qp_lt_sum. by eexists. + apply (irreflexive_eq (R:= Qclt) 1%Qp 1%Qp); [done|]. + eapply Qclt_le_trans; [apply Lt|done]. + Qed. + + Lemma WeakAuth_new_lock γ iS q: + WeakAuth γ (iS, None) ==∗ + WeakAuth γ (iS, Some $ Cinr (Excl (), to_agree q)) ∗ WkLock γ q. + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; [|by rewrite /= right_id]. apply prod_update; [done|]. simpl. + apply auth_update_alloc. apply prod_local_update; simpl; [done|]. + rewrite -(right_id None op (Some _)). + by apply op_local_update_discrete. + Qed. + + Lemma WeakAuth_lock_agree γ iS st q: + WeakAuth γ (iS, st) ∗ WkLock γ q -∗ + ⌜st ≡ Some (Cinr (Excl tt, to_agree q))⌝. + Proof. + rewrite -embed_sep -own_op. iIntros "own". + iDestruct (@own_valid _ arcUR with "own") + as %[[_ [[_ [?|INCL]%option_included]%prod_included [_ VAL]]%auth_valid_discrete_2] _]; + [done|]. iPureIntro. + destruct INCL as (x & y & Eq1 & Eq2 & INCL). simpl in *. inversion Eq1. + subst x st. destruct INCL as [Eq|INCL]. + - inversion Eq as [|? b Eq2 |]. subst. by rewrite -Eq2. + - apply csum_included in INCL as [?|[(?&?&?&?)|(?&[u v]&Eq&?&[IN1 IN2]%prod_included)]]; + [by subst y|done|..]. + subst. inversion Eq. clear Eq. subst. + move : VAL => [VAL1 /to_agree_uninj [? VAL2]]. destruct u as [[]|]; [|done]. + simpl in *. move : IN2. rewrite -VAL2. move => /to_agree_included <- //. + Qed. + + Lemma WeakAuth_unlock γ iS st q : + WeakAuth γ (iS, st) ∗ WkLock γ q ==∗ WeakAuth γ (iS, None). + Proof. + iIntros "own". iDestruct (WeakAuth_lock_agree with "own") as %Eq. + rewrite -embed_sep -own_op. + iMod (@own_update _ arcUR with "own") as "$"; [|done]. + apply prod_update; [|by rewrite /= right_id]. apply prod_update; [done|]. simpl. + rewrite Eq. apply auth_update_dealloc. apply prod_local_update; [done|]. + rewrite /= -{1}(right_id None op (Some _)). + apply (cancel_local_update_unit (Some _)), _. + Qed. +End ArcGhost. diff --git a/theories/typing/lib/arc.v b/theories/typing/lib/arc.v new file mode 100644 index 0000000000000000000000000000000000000000..03825ae3030bbd1c245c9dac03937e3118ad3168 --- /dev/null +++ b/theories/typing/lib/arc.v @@ -0,0 +1,108 @@ +From Coq.QArith Require Import Qcanon. + +From iris.proofmode Require Import tactics. +From iris.algebra Require Import auth csum frac agree. +From iris.bi Require Import fractional. + +From lrust.lang Require Import memcpy arc. +From lrust.lifetime Require Import at_borrow. +From lrust.typing Require Export type. +From lrust.typing Require Import typing option. + +From gpfsl.gps Require Import middleware protocols. + +Set Default Proof Using "Type". + +Definition arcN := lrustN .@ "arc". +Definition arc_invN := arcN .@ "inv". +Definition arc_shrN := arcN .@ "shr". +Definition arc_endN := arcN .@ "end". + +Section arc. + Context `{!typeG Σ, !arcG Σ}. + Local Notation vProp := (vProp Σ). + + (* Preliminary definitions. *) + Let P1 ν q := (q.[ν])%I. + Instance P1_fractional ν : Fractional (P1 ν). + Proof. unfold P1. apply _. Qed. + Let P2 l n := (⎡ † l…(2 + n) ⎤ ∗ (l +ₗ 2) ↦∗: λ vl, ⌜length vl = n⌝)%I. + + Definition arc_persist tid ν (γs γw γsw : gname) (l : loc) (ty : type) : vProp := + (is_arc (P1 ν) (P2 l ty.(ty_size)) arc_invN γs γw γsw l ∗ + (* We use this disjunction, and not simply [ty_shr] here, *) + (* because [weak_new] cannot prove ty_shr, even for a dead *) + (* lifetime. *) + (ty.(ty_shr) ν tid (l +ₗ 2) ∨ [†ν]) ∗ + □ (1.[ν] ={↑lftN ∪ ↑arc_endN,∅}▷=∗ + [†ν] ∗ ▷ (l +ₗ 2) ↦∗: ty.(ty_own) tid ∗ ⎡ † l…(2 + ty.(ty_size)) ⎤))%I. + + Global Instance arc_persist_ne tid ν γs γw γsw l n : + Proper (type_dist2 n ==> dist n) (arc_persist tid ν γs γw γsw l). + Proof. + unfold arc_persist, P1, P2. move => ???. + apply bi.sep_ne. + - apply is_arc_contractive; eauto. done. + solve_proper_core ltac:(fun _ => f_type_equiv || f_equiv). + - solve_proper_core ltac:(fun _ => exact: type_dist2_S || exact: type_dist2_dist || + f_type_equiv || f_contractive || f_equiv). + Qed. + + Lemma arc_persist_type_incl tid ν γs γw γsw l ty1 ty2: + type_incl ty1 ty2 -∗ arc_persist tid ν γs γw γsw l ty1 -∗ arc_persist tid ν γs γw γsw l ty2. + Proof. + iIntros "#(Heqsz & Hinclo & Hincls) #(?& Hs & Hvs)". + iDestruct "Heqsz" as %->. iFrame "#". iSplit. + - iDestruct "Hs" as "[?|?]"; last auto. iLeft. by iApply "Hincls". + - iIntros "!# Hν". iMod ("Hvs" with "Hν") as "H". iModIntro. iNext. + iMod "H" as "($ & H & $)". iDestruct "H" as (vl) "[??]". iExists _. + iFrame. by iApply "Hinclo". + Qed. + + Lemma arc_persist_send tid tid' ν γs γw γsw l ty `{!Send ty,!Sync ty} : + arc_persist tid ν γs γw γsw l ty -∗ arc_persist tid' ν γs γw γsw l ty. + Proof. + iIntros "#($ & ? & Hvs)". rewrite sync_change_tid. iFrame "#". + iIntros "!# Hν". iMod ("Hvs" with "Hν") as "H". iModIntro. iNext. + iMod "H" as "($ & H & $)". iDestruct "H" as (vl) "?". iExists _. + by rewrite send_change_tid. + Qed. + + (* Model of arc *) + (* The ty_own part of the arc type cointains either the + shared protocol or the full ownership of the + content. The reason is that get_mut does not have the + masks to rebuild the invariants. *) + Definition full_arc_own l ty tid : vProp := + (l ↦ #1 ∗ (l +ₗ 1) ↦ #1 ∗ ⎡ † l…(2 + ty.(ty_size)) ⎤ ∗ + ▷ (l +ₗ 2) ↦∗: ty.(ty_own) tid)%I. + Definition shared_arc_own l ty tid : vProp := + (∃ γs γw γsw ν q, arc_persist tid ν γs γw γsw l ty ∗ + strong_arc q l γs γw γsw ∗ q.[ν])%I. + Lemma arc_own_share E l ty tid : + ↑lftN ⊆ E → + ⎡ lft_ctx ⎤ -∗ full_arc_own l ty tid ={E}=∗ shared_arc_own l ty tid. + Proof. + iIntros (?) "#LFT (Hl1 & Hl2 & H† & Hown)". + iMod (lft_create with "LFT") as (ν) "[Hν #Hν†]"=>//. + (* TODO: We should consider changing the statement of + bor_create to dis-entangle the two masks such that this is no + longer necessary. *) + iApply fupd_trans. iApply (fupd_mask_mono (↑lftN))=>//. + iMod (bor_create _ ν with "LFT Hown") as "[HP HPend]"=>//. iModIntro. + iMod (ty_share with "LFT HP Hν") as "[#? Hν]"; first solve_ndisj. + iMod (create_arc (P1 ν) (P2 l ty.(ty_size)) arc_invN with "Hl1 Hl2 Hν") + as (γ q') "(#? & ? & ?)". + iExists _, _, _. iFrame "∗#". iCombine "H†" "HPend" as "H". + iMod (inv_alloc arc_endN _ ([†ν] ∨ _)%I with "[H]") as "#INV"; + first by iRight; iApply "H". iIntros "!> !# Hν". + iMod (inv_open with "INV") as "[[H†|[$ Hvs]] Hclose]"; + [set_solver|iDestruct (lft_tok_dead with "Hν H†") as ">[]"|]. + rewrite difference_union_distr_l_L difference_diag_L right_id_L + difference_disjoint_L; last solve_ndisj. + iMod ("Hν†" with "Hν") as "H". iModIntro. iNext. iApply fupd_trans. + iMod "H" as "#Hν". iMod ("Hvs" with "Hν") as "$". iIntros "{$Hν} !>". + iApply "Hclose". auto. + Qed. + +End arc. \ No newline at end of file