Library leuvenss.theories.shared_memory_stronger
From iris.algebra Require Import lib.frac_auth numbers.
From iris.program_logic Require Import weakestpre.
From iris.heap_lang Require Import adequacy proofmode notation.
From iris.heap_lang.lib Require Import par.
Definition prog : expr :=
let: "c" := ref #0 in
(par (λ: ≠, FAA "c" #1) (λ: ≠, FAA "c" #2));;
! "c".
Section proof.
Context `{!heapGS Σ, !spawnG Σ, inG Σ (frac_authUR natUR)}.
Definition inv_name := nroot .@ "inv".
Definition Sum (γ : gname) (n : nat) : iProp Σ := own γ (●F n).
Definition Left (γ : gname) (n : nat) : iProp Σ := own γ (◯F{1/2} n).
Definition Right (γ : gname) (n : nat) : iProp Σ := own γ (◯F{1/2} n).
Lemma Contr_alloc : ⊢ |==> ∃ γ, Sum γ 0 ∗ Left γ 0 ∗ Right γ 0.
Proof.
iMod (own_alloc (●F 0 ⋅ ◯F 0)) as (γ) "[HS [HL HR]]";
first by apply frac_auth_valid.
iModIntro. iExists _; iFrame.
Qed.
Lemma Contr_sum γ n m k :
Sum γ n -∗ Left γ m -∗ Right γ k -∗ ⌜n = (m + k)%nat⌝.
Proof.
iIntros "H1 H2 H3".
iCombine "H2" "H3" as "H23".
iDestruct (own_valid_2 with "H1 H23") as %->%frac_auth_agree_L.
done.
Qed.
Lemma Contr_incr_left γ n m k :
Sum γ n -∗ Left γ m -∗ |==> Sum γ (n + k) ∗ Left γ (m + k).
Proof.
iIntros "H1 H2".
iCombine "H1" "H2" as "H".
iMod (own_update _ _ (●F (n + k) ⋅ ◯F{1/2} (m + k)) with "H") as "[H1 H2]".
{ apply frac_auth_update, nat_local_update; lia. }
iFrame; done.
Qed.
Lemma Contr_incr_right γ n m k :
Sum γ n -∗ Right γ m -∗ |==> Sum γ (n + k) ∗ Right γ (m + k).
Proof.
iIntros "H1 H2".
iCombine "H1" "H2" as "H".
iMod (own_update _ _ (●F (n + k) ⋅ ◯F{1/2} (m + k)) with "H") as "[H1 H2]".
{ apply frac_auth_update, nat_local_update; lia. }
iFrame; done.
Qed.
Lemma prog_spec : {{{ True }}} prog {{{ n, RET #n; ⌜n = 3⌝%Z }}}.
Proof.
unfold prog.
iIntros (Φ) "_ HΦ".
wp_alloc c as "Hc".
wp_pures.
iMod Contr_alloc as (γ) "[HS [HL HR]]".
iMod (inv_alloc inv_name _ (∃ n : nat, c ↦ #n ∗ Sum γ n)%I with "[Hc HS]")
as "#inv".
{ iExists 0; iFrame. }
wp_apply (wp_par (λ _, Left γ 1)%I (λ _, Right γ 2)%I with "[HL] [HR]").
{ iInv inv_name as (n) ">[Hc HS]".
wp_faa.
iMod (Contr_incr_left _ _ _ 1 with "HS HL") as "[HS HL]".
iModIntro; iSplitR "HL"; last done.
iNext; iExists (n+1); iFrame.
replace ((n + 1)%nat : Z) with (n + 1)%Z by lia.
done. }
{ iInv inv_name as (n) ">[Hc HS]".
wp_faa.
iMod (Contr_incr_right _ _ _ 2 with "HS HR") as "[HS HR]".
iModIntro; iSplitR "HR"; last done.
iNext; iExists (n+2); iFrame.
replace ((n + 2)%nat : Z) with (n + 2)%Z by lia.
done. }
iIntros (v1 v2) "[HL HR]".
iNext.
wp_pures.
iInv inv_name as (n) ">[Hc HS]".
wp_load.
iDestruct (Contr_sum with "HS HL HR") as %Hn.
rewrite Hn; simpl in ×.
iModIntro; iSplitR "HΦ".
{ iNext; iExists _; iFrame. }
iApply "HΦ"; done.
Qed.
End proof.
Lemma prog_adequacy : adequate NotStuck prog {|heap := ∅; used_proph_id := ∅ |} (λ v _, v = #3).
Proof.
assert (∀ Σ, subG (GFunctor (frac_authUR natUR)) Σ → inG Σ (frac_authUR natUR)).
{ solve_inG. }
apply (heap_adequacy #[heapΣ; spawnΣ; GFunctor (frac_authUR natUR)]).
iIntros (?) "Hinv".
iApply prog_spec; first done.
iNext; iIntros (? ->); done.
Qed.
From iris.program_logic Require Import weakestpre.
From iris.heap_lang Require Import adequacy proofmode notation.
From iris.heap_lang.lib Require Import par.
Definition prog : expr :=
let: "c" := ref #0 in
(par (λ: ≠, FAA "c" #1) (λ: ≠, FAA "c" #2));;
! "c".
Section proof.
Context `{!heapGS Σ, !spawnG Σ, inG Σ (frac_authUR natUR)}.
Definition inv_name := nroot .@ "inv".
Definition Sum (γ : gname) (n : nat) : iProp Σ := own γ (●F n).
Definition Left (γ : gname) (n : nat) : iProp Σ := own γ (◯F{1/2} n).
Definition Right (γ : gname) (n : nat) : iProp Σ := own γ (◯F{1/2} n).
Lemma Contr_alloc : ⊢ |==> ∃ γ, Sum γ 0 ∗ Left γ 0 ∗ Right γ 0.
Proof.
iMod (own_alloc (●F 0 ⋅ ◯F 0)) as (γ) "[HS [HL HR]]";
first by apply frac_auth_valid.
iModIntro. iExists _; iFrame.
Qed.
Lemma Contr_sum γ n m k :
Sum γ n -∗ Left γ m -∗ Right γ k -∗ ⌜n = (m + k)%nat⌝.
Proof.
iIntros "H1 H2 H3".
iCombine "H2" "H3" as "H23".
iDestruct (own_valid_2 with "H1 H23") as %->%frac_auth_agree_L.
done.
Qed.
Lemma Contr_incr_left γ n m k :
Sum γ n -∗ Left γ m -∗ |==> Sum γ (n + k) ∗ Left γ (m + k).
Proof.
iIntros "H1 H2".
iCombine "H1" "H2" as "H".
iMod (own_update _ _ (●F (n + k) ⋅ ◯F{1/2} (m + k)) with "H") as "[H1 H2]".
{ apply frac_auth_update, nat_local_update; lia. }
iFrame; done.
Qed.
Lemma Contr_incr_right γ n m k :
Sum γ n -∗ Right γ m -∗ |==> Sum γ (n + k) ∗ Right γ (m + k).
Proof.
iIntros "H1 H2".
iCombine "H1" "H2" as "H".
iMod (own_update _ _ (●F (n + k) ⋅ ◯F{1/2} (m + k)) with "H") as "[H1 H2]".
{ apply frac_auth_update, nat_local_update; lia. }
iFrame; done.
Qed.
Lemma prog_spec : {{{ True }}} prog {{{ n, RET #n; ⌜n = 3⌝%Z }}}.
Proof.
unfold prog.
iIntros (Φ) "_ HΦ".
wp_alloc c as "Hc".
wp_pures.
iMod Contr_alloc as (γ) "[HS [HL HR]]".
iMod (inv_alloc inv_name _ (∃ n : nat, c ↦ #n ∗ Sum γ n)%I with "[Hc HS]")
as "#inv".
{ iExists 0; iFrame. }
wp_apply (wp_par (λ _, Left γ 1)%I (λ _, Right γ 2)%I with "[HL] [HR]").
{ iInv inv_name as (n) ">[Hc HS]".
wp_faa.
iMod (Contr_incr_left _ _ _ 1 with "HS HL") as "[HS HL]".
iModIntro; iSplitR "HL"; last done.
iNext; iExists (n+1); iFrame.
replace ((n + 1)%nat : Z) with (n + 1)%Z by lia.
done. }
{ iInv inv_name as (n) ">[Hc HS]".
wp_faa.
iMod (Contr_incr_right _ _ _ 2 with "HS HR") as "[HS HR]".
iModIntro; iSplitR "HR"; last done.
iNext; iExists (n+2); iFrame.
replace ((n + 2)%nat : Z) with (n + 2)%Z by lia.
done. }
iIntros (v1 v2) "[HL HR]".
iNext.
wp_pures.
iInv inv_name as (n) ">[Hc HS]".
wp_load.
iDestruct (Contr_sum with "HS HL HR") as %Hn.
rewrite Hn; simpl in ×.
iModIntro; iSplitR "HΦ".
{ iNext; iExists _; iFrame. }
iApply "HΦ"; done.
Qed.
End proof.
Lemma prog_adequacy : adequate NotStuck prog {|heap := ∅; used_proph_id := ∅ |} (λ v _, v = #3).
Proof.
assert (∀ Σ, subG (GFunctor (frac_authUR natUR)) Σ → inG Σ (frac_authUR natUR)).
{ solve_inG. }
apply (heap_adequacy #[heapΣ; spawnΣ; GFunctor (frac_authUR natUR)]).
iIntros (?) "Hinv".
iApply prog_spec; first done.
iNext; iIntros (? ->); done.
Qed.