Library zoo_saturn.mpsc_queue_2

From zoo Require Import
  prelude.
From zoo.common Require Import
  countable
  list.
From zoo.iris.base_logic Require Import
  lib.twins.
From zoo.language Require Import
  notations.
From zoo.diaframe Require Import
  diaframe.
From zoo_std Require Import
  option
  glist.
From zoo_saturn Require Export
  base
  mpsc_queue_2__code.
From zoo_saturn Require Import
  mpsc_queue_2__types.
From zoo Require Import
  options.

Implicit Types l : location.
Implicit Types v t : val.
Implicit Types vs front back : list val.
Implicit Types o : option val.

Class MpscQueue2G Σ `{zoo_G : !ZooG Σ} :=
  { #[local] mpsc_queue_2_G_twins_G :: TwinsG Σ (leibnizO (list val))
  }.

Definition mpsc_queue_2_Σ :=
  #[twins_Σ (leibnizO (list val))
  ].
#[global] Instance subG_mpsc_queue_2_Σ Σ `{zoo_G : !ZooG Σ} :
  subG mpsc_queue_2_Σ Σ
  MpscQueue2G Σ.

Section mpsc_queue_2_G.
  Context `{mpsc_queue_2_G : MpscQueue2G Σ}.

  Record metadata :=
    { metadata_model : gname
    ; metadata_front : gname
    }.
  Implicit Types γ : metadata.

  #[local] Instance metadata_eq_dec : EqDecision metadata :=
    ltac:(solve_decision).
  #[local] Instance metadata_countable :
    Countable metadata.

  #[local] Definition model₁' γ_model vs :=
    twins_twin1 γ_model (DfracOwn 1) vs.
  #[local] Definition model₁ γ vs :=
    model₁' γ.(metadata_model) vs.
  #[local] Definition model₂' γ_model vs :=
    twins_twin2 γ_model vs.
  #[local] Definition model₂ γ vs :=
    model₂' γ.(metadata_model) vs.

  #[local] Definition front₁' γ_front front :=
    twins_twin1 γ_front (DfracOwn 1) front.
  #[local] Definition front₁ γ front :=
    front₁' γ.(metadata_front) front.
  #[local] Definition front₂' γ_model front :=
    twins_twin2 γ_model front.
  #[local] Definition front₂ γ front :=
    front₂' γ.(metadata_front) front.

  #[local] Definition inv_inner l γ : iProp Σ :=
     front back,
    front₂ γ front
    l.[back] glist_to_val back
    model₂ γ (front ++ reverse back).
  #[local] Instance : CustomIpat "inv_inner" :=
    " ( %front{} & %back{} & >Hfront₂ & >Hl_back & >Hmodel₂ ) ".
  Definition mpsc_queue_2_inv t ι : iProp Σ :=
     l γ,
    t = #l
    meta l nroot γ
    inv ι (inv_inner l γ).
  #[local] Instance : CustomIpat "inv" :=
    " ( %l & %γ & -> & #Hmeta & #Hinv ) ".

  Definition mpsc_queue_2_model t vs : iProp Σ :=
     l γ,
    t = #l
    meta l nroot γ
    model₁ γ vs.
  #[local] Instance : CustomIpat "model" :=
    " ( %l{;_} & %γ{;_} & %Heq{} & Hmeta_{} & Hmodel₁{_{}} ) ".

  Definition mpsc_queue_2_consumer t : iProp Σ :=
     l γ front,
    t = #l
    meta l nroot γ
    l.[front] glist_to_val front
    front₁ γ front.
  #[local] Instance : CustomIpat "consumer" :=
    " ( %l_ & %γ_ & %front & %Heq & Hmeta_ & Hl_front & Hfront₁ ) ".

  #[global] Instance mpsc_queue_2_model_timeless t vs :
    Timeless (mpsc_queue_2_model t vs).
  #[global] Instance mpsc_queue_2_consumer_timeless t :
    Timeless (mpsc_queue_2_consumer t ).

  #[global] Instance mpsc_queue_2_inv_persistent t ι :
    Persistent (mpsc_queue_2_inv t ι).

  #[local] Lemma model_alloc :
     |==>
       γ_model,
      model₁' γ_model []
      model₂' γ_model [].
  #[local] Lemma model₁_exclusive γ vs1 vs2 :
    model₁ γ vs1 -∗
    model₁ γ vs2 -∗
    False.
  #[local] Lemma model_agree γ vs1 vs2 :
    model₁ γ vs1 -∗
    model₂ γ vs2 -∗
    vs1 = vs2.
  #[local] Lemma model_update {γ vs1 vs2} vs :
    model₁ γ vs1 -∗
    model₂ γ vs2 ==∗
      model₁ γ vs
      model₂ γ vs.

  #[local] Lemma front_alloc :
     |==>
       γ_front,
      front₁' γ_front []
      front₂' γ_front [].
  #[local] Lemma front_agree γ front1 front2 :
    front₁ γ front1 -∗
    front₂ γ front2 -∗
    front1 = front2.
  #[local] Lemma front_update {γ front1 front2} front :
    front₁ γ front1 -∗
    front₂ γ front2 ==∗
      front₁ γ front
      front₂ γ front.

  Lemma mpsc_queue_2_model_exclusive t vs1 vs2 :
    mpsc_queue_2_model t vs1 -∗
    mpsc_queue_2_model t vs2 -∗
    False.

  Lemma mpsc_queue_2_consumer_exclusive t :
    mpsc_queue_2_consumer t -∗
    mpsc_queue_2_consumer t -∗
    False.

  Lemma mpsc_queue_2٠create𑁒spec ι :
    {{{
      True
    }}}
      mpsc_queue_2٠create ()
    {{{
      t
    , RET t;
      mpsc_queue_2_inv t ι
      mpsc_queue_2_model t []
      mpsc_queue_2_consumer t
    }}}.

  Lemma mpsc_queue_2٠is_empty𑁒spec t ι :
    <<<
      mpsc_queue_2_inv t ι
      mpsc_queue_2_consumer t
    | ∀∀ vs,
      mpsc_queue_2_model t vs
    >>>
      mpsc_queue_2٠is_empty t @ ι
    <<<
      mpsc_queue_2_model t vs
    | RET #(bool_decide (vs = []%list));
      mpsc_queue_2_consumer t
    >>>.

  Lemma mpsc_queue_2٠push_front𑁒spec t ι v :
    <<<
      mpsc_queue_2_inv t ι
      mpsc_queue_2_consumer t
    | ∀∀ vs,
      mpsc_queue_2_model t vs
    >>>
      mpsc_queue_2٠push_front t v @ ι
    <<<
      mpsc_queue_2_model t (v :: vs)
    | RET ();
      mpsc_queue_2_consumer t
    >>>.

  Lemma mpsc_queue_2٠push_back𑁒spec t ι v :
    <<<
      mpsc_queue_2_inv t ι
    | ∀∀ vs,
      mpsc_queue_2_model t vs
    >>>
      mpsc_queue_2٠push_back t v @ ι
    <<<
      mpsc_queue_2_model t (vs ++ [v])
    | RET ();
      True
    >>>.

  Lemma mpsc_queue_2٠pop𑁒spec t ι :
    <<<
      mpsc_queue_2_inv t ι
      mpsc_queue_2_consumer t
    | ∀∀ vs,
      mpsc_queue_2_model t vs
    >>>
      mpsc_queue_2٠pop t @ ι
    <<<
      mpsc_queue_2_model t (tail vs)
    | RET head vs;
      mpsc_queue_2_consumer t
    >>>.
End mpsc_queue_2_G.

From zoo_saturn Require
  mpsc_queue_2__opaque.

#[global] Opaque mpsc_queue_2_inv.
#[global] Opaque mpsc_queue_2_model.
#[global] Opaque mpsc_queue_2_consumer.