one_shot.v 5.25 KB
Newer Older
1 2
From iris.proofmode Require Import tactics.
From iris.algebra Require Import excl agree csum.
3 4
From iris.program_logic Require Export weakestpre hoare.
From iris.heap_lang Require Export lang.
Ralf Jung's avatar
Ralf Jung committed
5 6
From iris.heap_lang Require Import assert proofmode notation adequacy.
From iris.heap_lang.lib Require Import par.
7
Set Default Proof Using "Type".
Ralf Jung's avatar
Ralf Jung committed
8

Ralf Jung's avatar
Ralf Jung committed
9 10 11
(** This is the introductory example from the "Iris from the Ground Up" journal
paper. *)

Ralf Jung's avatar
Ralf Jung committed
12
Definition one_shot_example : val := λ: <>,
13
  let: "x" := ref NONE in (
Ralf Jung's avatar
Ralf Jung committed
14
  (* tryset *) (λ: "n",
15
    CAS "x" NONE (SOME "n")),
Ralf Jung's avatar
Ralf Jung committed
16
  (* check  *) (λ: <>,
17 18
    let: "y" := !"x" in λ: <>,
    match: "y" with
19 20
      NONE => #()
    | SOME "n" =>
21
       match: !"x" with
22 23
         NONE => assert: #false
       | SOME "m" => assert: "n" = "m"
Ralf Jung's avatar
Ralf Jung committed
24 25 26
       end
    end)).

27
Definition one_shotR := csumR (exclR unitO) (agreeR ZO).
Robbert Krebbers's avatar
Robbert Krebbers committed
28 29
Definition Pending : one_shotR := Cinl (Excl ()).
Definition Shot (n : Z) : one_shotR := Cinr (to_agree n).
30

31
Class one_shotG Σ := { one_shot_inG :> inG Σ one_shotR }.
32
Definition one_shotΣ : gFunctors := #[GFunctor one_shotR].
33
Instance subG_one_shotΣ {Σ} : subG one_shotΣ Σ  one_shotG Σ.
34
Proof. solve_inG. Qed.
Jacques-Henri Jourdan's avatar
Jacques-Henri Jourdan committed
35

Ralf Jung's avatar
Ralf Jung committed
36
Section proof.
37
Local Set Default Proof Using "Type*".
38
Context `{!heapG Σ, !one_shotG Σ}.
Ralf Jung's avatar
Ralf Jung committed
39

40
Definition one_shot_inv (γ : gname) (l : loc) : iProp Σ :=
41
  (l  NONEV  own γ Pending   n : Z, l  SOMEV #n  own γ (Shot n))%I.
Ralf Jung's avatar
Ralf Jung committed
42

43
Lemma wp_one_shot (Φ : val  iProp Σ) :
44
  ( f1 f2 : val,
Ralf Jung's avatar
Ralf Jung committed
45
    ( n : Z,  WP f1 #n {{ w, w = #true  w = #false }}) 
46
     WP f2 #() {{ g,  WP g #() {{ _, True }} }} - Φ (f1,f2)%V)
Ralf Jung's avatar
Ralf Jung committed
47 48
   WP one_shot_example #() {{ Φ }}.
Proof.
49
  iIntros "Hf /=". pose proof (nroot .@ "N") as N.
Jacques-Henri Jourdan's avatar
Jacques-Henri Jourdan committed
50
  rewrite -wp_fupd. wp_lam. wp_alloc l as "Hl".
51 52
  iMod (own_alloc Pending) as (γ) "Hγ"; first done.
  iMod (inv_alloc N _ (one_shot_inv γ l) with "[Hl Hγ]") as "#HN".
Robbert Krebbers's avatar
Robbert Krebbers committed
53
  { iNext. iLeft. by iSplitL "Hl". }
Jacques-Henri Jourdan's avatar
Jacques-Henri Jourdan committed
54
  wp_pures. iModIntro. iApply "Hf"; iSplit.
55
  - iIntros (n) "!#". wp_lam. wp_pures. wp_bind (CmpXchg _ _ _).
56 57
    iInv N as ">[[Hl Hγ]|H]"; last iDestruct "H" as (m) "[Hl Hγ]".
    + iMod (own_update with "Hγ") as "Hγ".
58
      { by apply cmra_update_exclusive with (y:=Shot n). }
59
      wp_cmpxchg_suc. iModIntro. iSplitL; last (wp_pures; by eauto).
60
      iNext; iRight; iExists n; by iFrame.
61
    + wp_cmpxchg_fail. iModIntro. iSplitL; last (wp_pures; by eauto).
62
      rewrite /one_shot_inv; eauto 10.
63
  - iIntros "!# /=". wp_lam. wp_bind (! _)%E.
64
    iInv N as ">Hγ".
Ralf Jung's avatar
Ralf Jung committed
65 66
    iAssert ( v, l  v  ((v = NONEV  own γ Pending) 
        n : Z, v = SOMEV #n  own γ (Shot n)))%I with "[Hγ]" as "Hv".
67
    { iDestruct "Hγ" as "[[Hl Hγ]|Hl]"; last iDestruct "Hl" as (m) "[Hl Hγ]".
68 69
      + iExists NONEV. iFrame. eauto.
      + iExists (SOMEV #m). iFrame. eauto. }
70
    iDestruct "Hv" as (v) "[Hl Hv]". wp_load.
Ralf Jung's avatar
Ralf Jung committed
71 72
    iAssert (one_shot_inv γ l  (v = NONEV   n : Z,
      v = SOMEV #n  own γ (Shot n)))%I with "[Hl Hv]" as "[Hinv #Hv]".
73
    { iDestruct "Hv" as "[[% ?]|Hv]"; last iDestruct "Hv" as (m) "[% ?]"; subst.
74
      + Show. iSplit. iLeft; by iSplitL "Hl". eauto.
75
      + iSplit. iRight; iExists m; by iSplitL "Hl". eauto. }
76
    iSplitL "Hinv"; first by eauto.
Jacques-Henri Jourdan's avatar
Jacques-Henri Jourdan committed
77 78 79 80
    iModIntro. wp_pures. iIntros "!#". wp_lam.
    iDestruct "Hv" as "[%|Hv]"; last iDestruct "Hv" as (m) "[% Hγ']";
      subst; wp_match; [done|].
    wp_bind (! _)%E.
81
    iInv N as "[[Hl >Hγ]|H]"; last iDestruct "H" as (m') "[Hl Hγ]".
82
    { by iDestruct (own_valid_2 with "Hγ Hγ'") as %?. }
83
    wp_load. Show.
84
    iDestruct (own_valid_2 with "Hγ Hγ'") as %?%agree_op_invL'; subst.
85
    iModIntro. iSplitL "Hl".
86
    { iNext; iRight; by eauto. }
Jacques-Henri Jourdan's avatar
Jacques-Henri Jourdan committed
87
    wp_apply wp_assert. wp_pures. by case_bool_decide.
Ralf Jung's avatar
Ralf Jung committed
88 89
Qed.

90
Lemma ht_one_shot (Φ : val  iProp Σ) :
91
  {{ True }} one_shot_example #()
92
    {{ ff,
Ralf Jung's avatar
Ralf Jung committed
93
      ( n : Z, {{ True }} Fst ff #n {{ w, w = #true  w = #false }}) 
94
      {{ True }} Snd ff #() {{ g, {{ True }} g #() {{ _, True }} }}
Ralf Jung's avatar
Ralf Jung committed
95 96
    }}.
Proof.
97
  iIntros "!# _". iApply wp_one_shot. iIntros (f1 f2) "[#Hf1 #Hf2]"; iSplit.
Jacques-Henri Jourdan's avatar
Jacques-Henri Jourdan committed
98 99
  - iIntros (n) "!# _". wp_apply "Hf1".
  - iIntros "!# _". wp_apply (wp_wand with "Hf2"). by iIntros (v) "#? !# _".
Ralf Jung's avatar
Ralf Jung committed
100 101
Qed.
End proof.
Ralf Jung's avatar
Ralf Jung committed
102 103 104 105 106 107 108 109 110 111

(* Have a client with a closed proof. *)
Definition client : expr :=
  let: "ff" := one_shot_example #() in
  (Fst "ff" #5 ||| let: "check" := Snd "ff" #() in "check" #()).

Section client.
  Context `{!heapG Σ, !one_shotG Σ, !spawnG Σ}.

  Lemma client_safe : WP client {{ _, True }}%I.
112
  Proof using Type*.
Ralf Jung's avatar
Ralf Jung committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    rewrite /client. wp_apply wp_one_shot. iIntros (f1 f2) "[#Hf1 #Hf2]".
    wp_let. wp_apply wp_par.
    - wp_apply "Hf1".
    - wp_proj. wp_bind (f2 _)%E. iApply wp_wand; first by iExact "Hf2".
      iIntros (check) "Hcheck". wp_pures. iApply "Hcheck".
    - auto.
  Qed.
End client.

(** Put together all library functors. *)
Definition clientΣ : gFunctors := #[ heapΣ; one_shotΣ; spawnΣ ].
(** This lemma implicitly shows that these functors are enough to meet
all library assumptions. *)
Lemma client_adequate σ : adequate NotStuck client σ (λ _ _, True).
Proof. apply (heap_adequacy clientΣ)=> ?. apply client_safe. Qed.

(* Since we check the output of the test files, this means
our test suite will fail if we ever accidentally add an axiom
to anything used by this proof. *)
Print Assumptions client_adequate.