Library zoo_saturn.inf_queue_mpmc_1

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.common.function.
Require Import zoo.iris.bi.big_op.
Require Import zoo.iris.base_logic.lib.twins.
Require Import zoo.iris.base_logic.lib.mono_list.
Require Import zoo.iris.base_logic.lib.saved_pred.
Require Import zoo.iris.base_logic.lib.oneshot.
Require Import zoo.base.
Require Import zoo.program_logic.prophet_nat.
Require Import zoo_std.option.
Require Export zoo_saturn.inf_queue_mpmc_1__code.
Require Import zoo_saturn.inf_queue_mpmc_1__types.
Require Import zoo.options.

Implicit Type b : bool.
Implicit Type front back : nat.
Implicit Type v : val.
Implicit Type vs hist : list val.
Implicit Type slot : optional val.
Implicit Type slots : nat optional val.
Implicit Type η : gname.
Implicit Type ηs : list gname.

Class InfQueueMpmc1G Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] inf_queue_mpmc_1۰G۰inf_array۰G :: InfArrayG Σ
  ; #[local] inf_queue_mpmc_1۰G۰model۰G :: TwinsG Σ (leibnizO (list val))
  ; #[local] inf_queue_mpmc_1۰G۰history۰G :: MonoListG Σ val
  ; #[local] inf_queue_mpmc_1۰G۰consumer۰G :: SavedPredG Σ val
  ; #[local] inf_queue_mpmc_1۰G۰consumers۰G :: MonoListG Σ gname
  ; #[local] inf_queue_mpmc_1۰G۰token۰G :: OneshotG Σ () ()
  ; #[local] inf_queue_mpmc_1۰G۰tokens۰G :: MonoListG Σ gname
  }.

Definition inf_queue_mpmc_1۰Σ :=
  #[inf_array۰Σ
  ; twins۰Σ (leibnizO (list val))
  ; mono_list۰Σ val
  ; saved_pred۰Σ val
  ; mono_list۰Σ gname
  ; oneshot۰Σ () ()
  ; mono_list۰Σ gname
  ].
#[global] Instance subGinf_queue_mpmc_1۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG inf_queue_mpmc_1۰Σ Σ
  InfQueueMpmc1G Σ.

Module base.
  Section inf_queue_mpmc_1۰G.
    Context `{inf_queue_mpmc_1۰G : InfQueueMpmc1G Σ}.

    Implicit Type t : location.
    Implicit Type Ψ : val iProp Σ.

    Record inf_queue_mpmc_1۰name :=
      { inf_queue_mpmc_1۰name۰data : val
      ; inf_queue_mpmc_1۰name۰inv : namespace
      ; inf_queue_mpmc_1۰name۰model : gname
      ; inf_queue_mpmc_1۰name۰history : gname
      ; inf_queue_mpmc_1۰name۰consumers : gname
      ; inf_queue_mpmc_1۰name۰tokens : gname
      }.
    Implicit Type γ : inf_queue_mpmc_1۰name.

    #[global] Instance inf_queue_mpmc_1۰nameeq_dec : EqDecision inf_queue_mpmc_1۰name :=
      ltac:(solve_decision).
    #[global] Instance inf_queue_mpmc_1۰namecountable :
      Countable inf_queue_mpmc_1۰name.

    #[local] Definition model₁' γ_model vs :=
      twins۰twin₁ γ_model (DfracOwn 1) vs.
    #[local] Definition model₁ γ :=
      model₁' γ.(inf_queue_mpmc_1۰name۰model).
    #[local] Definition model₂' γ_model vs :=
      twins۰twin₂ γ_model vs.
    #[local] Definition model₂ γ :=
      model₂' γ.(inf_queue_mpmc_1۰name۰model).

    #[local] Definition history۰auth' γ_history hist :=
      mono_list۰auth γ_history (DfracOwn 1) hist.
    #[local] Definition history۰auth γ :=
      history۰auth' γ.(inf_queue_mpmc_1۰name۰history).
    #[local] Definition history۰at γ i v :=
      mono_list۰at γ.(inf_queue_mpmc_1۰name۰history) i v.

    #[local] Definition consumers۰auth' γ_consumers i : iProp Σ :=
       ηs,
      mono_list۰auth γ_consumers (DfracOwn 1) ηs
      length ηs = i.
    #[local] Definition consumers۰auth γ i :=
      consumers۰auth' γ.(inf_queue_mpmc_1۰name۰consumers) i.
    #[local] Instance : CustomIpat "consumers۰auth" :=
      " ( %ηs{} & Hauth{} & %Hηs{} ) ".
    #[local] Definition consumers۰at γ i Ψ : iProp Σ :=
       η,
      mono_list۰at γ.(inf_queue_mpmc_1۰name۰consumers) i η
      saved_pred η Ψ.
    #[local] Instance : CustomIpat "consumers۰at" :=
      " ( %η{} & Hat{} & HΨ{} ) ".
    #[local] Definition consumers۰lb γ i : iProp Σ :=
       ηs,
      length ηs = i
      mono_list۰lb γ.(inf_queue_mpmc_1۰name۰consumers) ηs.
    #[local] Instance : CustomIpat "consumers۰lb" :=
      " ( %ηs{} & %Hηs{} & Hlb{} ) ".

    #[local] Definition tokens۰auth' γ_tokens i : iProp Σ :=
       ηs,
      mono_list۰auth γ_tokens (DfracOwn 1) ηs
      length ηs = i.
    #[local] Definition tokens۰auth γ i :=
      tokens۰auth' γ.(inf_queue_mpmc_1۰name۰tokens) i.
    #[local] Instance : CustomIpat "tokens۰auth" :=
      " ( %ηs{} & Hauth{} & %Hηs{} ) ".
    #[local] Definition tokens۰pending γ i : iProp Σ :=
       η,
      mono_list۰at γ.(inf_queue_mpmc_1۰name۰tokens) i η
      oneshot۰pending η (DfracOwn 1) ().
    #[local] Instance : CustomIpat "tokens۰pending" :=
      " ( %η{} & Hat{} & Hpending{} ) ".
    #[local] Definition tokens۰done γ i : iProp Σ :=
       η,
      mono_list۰at γ.(inf_queue_mpmc_1۰name۰tokens) i η
      oneshot۰shot η ().
    #[local] Instance : CustomIpat "tokens۰done" :=
      " ( %η{} & Hat{} & Hshot{} ) ".

    #[local] Definition consumer۰au γ Ψ : iProp Σ :=
      AU <{
        ∃∃ vs,
        model₁ γ vs
      }> @ γ.(inf_queue_mpmc_1۰name۰inv), <{
        ∀∀ v vs',
        vs = v :: vs'
        model₁ γ vs'
      , COMM
        Ψ v
      }>.

    #[local] Definition slot۰model γ i slot : iProp Σ :=
      match slot with
      | Something v
          history۰at γ i v
      | Anything
          tokens۰done γ i
      | Nothing
          True
      end.
    #[local] Definition inv۰inner t γ : iProp Σ :=
       front back hist slots,
      t.[front] #front
      t.[back] #back
      inf_array۰model γ.(inf_queue_mpmc_1۰name۰data) (optional۰to_val slots)
      history۰auth γ hist
      length hist = back
      model₂ γ (drop front hist)
      consumers۰auth γ front
      tokens۰auth γ (front `max` back)
      ( [∗ list] i seq 0 back,
          tokens۰pending γ i
         Ψ,
          consumers۰at γ i Ψ
          ( tokens۰done γ i
           v,
            history۰at γ i v
            Ψ v
          )
      )
      ( [∗ list] i seq back (front - back),
         Ψ,
        consumers۰at γ i Ψ
        consumer۰au γ Ψ
      )
      ( i, slot۰model γ i (slots i)).
    #[local] Instance : CustomIpat "inv۰inner" :=
      " ( %front{} & %back{} & %hist{} & %slots{} & Ht_front & Ht_back & >Hdata_model & >Hhistory_auth & >%Hhist{} & Hmodel₂ & Hconsumers_auth & Htokens_auth & Hpast & Hwaiters & Hslots ) ".
    Definition inv' t γ : iProp Σ :=
      t.[data] γ.(inf_queue_mpmc_1۰name۰data)
      inf_array۰inv γ.(inf_queue_mpmc_1۰name۰data)
      inv γ.(inf_queue_mpmc_1۰name۰inv) (inv۰inner t γ).
    #[local] Instance : CustomIpat "inv'" :=
      " ( #Ht_data & #Hdata_inv & #Hinv ) ".
    Definition inf_queue_mpmc_1۰inv t γ ι : iProp Σ :=
      ι = γ.(inf_queue_mpmc_1۰name۰inv)
      inv' t γ.
    #[local] Instance : CustomIpat "inv" :=
      " ( -> & (:inv') ) ".

    Definition inf_queue_mpmc_1۰model :=
      model₁.
    #[local] Instance : CustomIpat "model" :=
      " Hmodel₁{_{}} ".

    #[local] Instance tokens۰pendingtimeless γ i :
      Timeless (tokens۰pending γ i).
    #[local] Instance tokens۰donetimeless γ i :
      Timeless (tokens۰done γ i).
    #[local] Instance slot۰modeltimeless γ i slot :
      Timeless (slot۰model γ i slot).
    #[global] Instance inf_queue_mpmc_1۰modeltimeless γ vs :
      Timeless (inf_queue_mpmc_1۰model γ vs).

    #[local] Instance consumers۰atpersistent γ i Ψ :
      Persistent (consumers۰at γ i Ψ).
    #[local] Instance consumers۰lbpersistent γ i :
      Persistent (consumers۰lb γ i).
    #[local] Instance tokens۰donepersistent γ i :
      Persistent (tokens۰done γ i).
    #[local] Instance slot۰modelpersistent γ i slot :
      Persistent (slot۰model γ i slot).
    #[global] Instance inf_queue_mpmc_1۰invpersistent t γ ι :
      Persistent (inf_queue_mpmc_1۰inv t γ ι).

    #[local] Lemma modelalloc :
       |==>
         γ_model,
        model₁' γ_model []
        model₂' γ_model [].
    #[local] Lemma model₁exclusive γ vs1 vs2 :
      model₁ γ vs1 -∗
      model₁ γ vs2 -∗
      False.
    #[local] Lemma modelagree γ vs1 vs2 :
      model₁ γ vs1 -∗
      model₂ γ vs2 -∗
      vs1 = vs2.
    #[local] Lemma modelupdate {γ vs1 vs2} vs :
      model₁ γ vs1 -∗
      model₂ γ vs2 ==∗
        model₁ γ vs
        model₂ γ vs.

    #[local] Lemma historyalloc :
       |==>
         γ_history,
        history۰auth' γ_history [].
    #[local] Lemma history۰atvalid γ hist i v :
      history۰auth γ hist -∗
      history۰at γ i v -∗
      hist !! i = Some v.
    #[local] Lemma history۰atagree γ i v1 v2 :
      history۰at γ i v1 -∗
      history۰at γ i v2 -∗
      v1 = v2.
    #[local] Lemma history۰atget {γ hist} i v :
      hist !! i = Some v
      history۰auth γ hist
      history۰at γ i v.
    #[local] Lemma historyupdate {γ hist} v :
      history۰auth γ hist |==>
        history۰auth γ (hist ++ [v])
        history۰at γ (length hist) v.

    #[local] Lemma consumersalloc :
       |==>
         γ_consumers,
        consumers۰auth' γ_consumers 0.
    #[local] Lemma consumers۰atvalid γ i j Ψ :
      consumers۰auth γ i -∗
      consumers۰at γ j Ψ -∗
      j < i.
    #[local] Lemma consumers۰atagree γ i Ψ1 Ψ2 v :
      consumers۰at γ i Ψ1 -∗
       consumers۰at γ i Ψ2 -∗
       Ψ2 v -∗
      ▷^2 Ψ1 v.
    #[local] Lemma consumers۰lbvalid γ i j :
      consumers۰auth γ i -∗
      consumers۰lb γ j -∗
      j i.
    #[local] Lemma consumers۰lbget γ i :
      consumers۰auth γ i
      consumers۰lb γ i.
    #[local] Lemma consumersupdate {γ i} Ψ :
      consumers۰auth γ i |==>
        consumers۰auth γ ˖i
        consumers۰at γ i Ψ.
    Opaque consumers۰auth'.
    Opaque consumers۰at.
    Opaque consumers۰lb.

    #[local] Lemma tokensalloc :
       |==>
         γ_tokens,
        tokens۰auth' γ_tokens 0.
    #[local] Lemma tokens۰pendingexclusive γ i :
      tokens۰pending γ i -∗
      tokens۰pending γ i -∗
      False.
    #[local] Lemma tokens۰pendingdone γ i :
      tokens۰pending γ i -∗
      tokens۰done γ i -∗
      False.
    #[local] Lemma tokensupdate {γ} i :
      tokens۰auth γ i |==>
        tokens۰auth γ ˖i
        tokens۰pending γ i.
    #[local] Lemma tokens۰pendingupdate γ i :
      tokens۰pending γ i |==>
      tokens۰done γ i.
    Opaque tokens۰auth'.
    Opaque tokens۰pending.
    Opaque tokens۰done.

    Lemma inf_queue_mpmc_1۰modelexclusive γ vs1 vs2 :
      inf_queue_mpmc_1۰model γ vs1 -∗
      inf_queue_mpmc_1۰model γ vs2 -∗
      False.

    Lemma inf_queue_mpmc_1٠createspec ι :
      {{{
        True
      }}}
        inf_queue_mpmc_1٠create ()
      {{{
        t γ
      , RET #t;
        meta_token t
        inf_queue_mpmc_1۰inv t γ ι
        inf_queue_mpmc_1۰model γ []
      }}}.

    Lemma inf_queue_mpmc_1٠sizespec t γ ι :
      <<<
        inf_queue_mpmc_1۰inv t γ ι
      | ∀∀ vs,
        inf_queue_mpmc_1۰model γ vs
      >>>
        inf_queue_mpmc_1٠size #t @ ι
      <<<
        inf_queue_mpmc_1۰model γ vs
      | RET #(length vs);
        True
      >>>.

    Lemma inf_queue_mpmc_1٠is_emptyspec t γ ι :
      <<<
        inf_queue_mpmc_1۰inv t γ ι
      | ∀∀ vs,
        inf_queue_mpmc_1۰model γ vs
      >>>
        inf_queue_mpmc_1٠is_empty #t @ ι
      <<<
        inf_queue_mpmc_1۰model γ vs
      | RET #(bool_decide (vs = []%list));
        True
      >>>.

    Lemma inf_queue_mpmc_1٠is_empty_weakspec t γ ι :
      <<<
        inf_queue_mpmc_1۰inv t γ ι
      | ∀∀ vs,
        inf_queue_mpmc_1۰model γ vs
      >>>
        inf_queue_mpmc_1٠is_empty_weak #t @ ι
      <<<
        ∃∃ b,
        if b then vs = [] else True
        inf_queue_mpmc_1۰model γ vs
      | RET #b;
        True
      >>>.

    Lemma inf_queue_mpmc_1٠pushspec t γ ι v :
      <<<
        inf_queue_mpmc_1۰inv t γ ι
      | ∀∀ vs,
        inf_queue_mpmc_1۰model γ vs
      >>>
        inf_queue_mpmc_1٠push #t v @ ι
      <<<
        inf_queue_mpmc_1۰model γ (vs ++ [v])
      | RET ();
        True
      >>>.

    #[local] Lemma inf_queue_mpmc_1٠pop₁spec t γ front Ψ :
      {{{
        inv' t γ
        consumers۰at γ front Ψ
        tokens۰pending γ front
      }}}
        inf_queue_mpmc_1٠pop₁ #t #front
      {{{
        v
      , RET v;
        Ψ v
      }}}.
    Lemma inf_queue_mpmc_1٠popspec t γ ι :
      <<<
        inf_queue_mpmc_1۰inv t γ ι
      | ∀∀ vs,
        inf_queue_mpmc_1۰model γ vs
      >>>
        inf_queue_mpmc_1٠pop #t @ ι
      <<<
        ∃∃ v vs',
        vs = v :: vs'
        inf_queue_mpmc_1۰model γ vs'
      | RET v;
        True
      >>>.

    Lemma inf_queue_mpmc_1٠try_popspec t γ ι :
      <<<
        inf_queue_mpmc_1۰inv t γ ι
      | ∀∀ vs,
        inf_queue_mpmc_1۰model γ vs
      >>>
        inf_queue_mpmc_1٠try_pop #t @ ι
      <<<
        inf_queue_mpmc_1۰model γ (tail vs)
      | RET head vs;
        True
      >>>.
  End inf_queue_mpmc_1۰G.

  #[global] Opaque inf_queue_mpmc_1۰inv.
  #[global] Opaque inf_queue_mpmc_1۰model.
End base.

Require zoo_saturn.inf_queue_mpmc_1__opaque.

Section inf_queue_mpmc_1۰G.
  Context `{inf_queue_mpmc_1۰G : InfQueueMpmc1G Σ}.

  Implicit Type 𝑡 : location.
  Implicit Type t : val.

  Definition inf_queue_mpmc_1۰inv t ι : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    𝑡 γ
    base.inf_queue_mpmc_1۰inv 𝑡 γ ι.
  #[local] Instance : CustomIpat "inv" :=
    " ( %𝑡{} & %γ{} & {%Heq{};->} & #Hmeta{_{}} & Hinv{_{}} ) ".

  Definition inf_queue_mpmc_1۰model t vs : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    𝑡 γ
    base.inf_queue_mpmc_1۰model γ vs.
  #[local] Instance : CustomIpat "model" :=
    " ( %𝑡{} & %γ{} & {%Heq{};->} & Hmeta{_{}} & Hmodel{_{}} ) ".

  #[global] Instance inf_queue_mpmc_1۰modeltimeless t vs :
    Timeless (inf_queue_mpmc_1۰model t vs).

  #[global] Instance inf_queue_mpmc_1۰invpersistent t ι :
    Persistent (inf_queue_mpmc_1۰inv t ι).

  Lemma inf_queue_mpmc_1۰modelexclusive t vs1 vs2 :
    inf_queue_mpmc_1۰model t vs1 -∗
    inf_queue_mpmc_1۰model t vs2 -∗
    False.

  Lemma inf_queue_mpmc_1٠createspec ι :
    {{{
      True
    }}}
      inf_queue_mpmc_1٠create ()
    {{{
      t
    , RET t;
      inf_queue_mpmc_1۰inv t ι
      inf_queue_mpmc_1۰model t []
    }}}.

  Lemma inf_queue_mpmc_1٠sizespec t ι :
    <<<
      inf_queue_mpmc_1۰inv t ι
    | ∀∀ vs,
      inf_queue_mpmc_1۰model t vs
    >>>
      inf_queue_mpmc_1٠size t @ ι
    <<<
      inf_queue_mpmc_1۰model t vs
    | RET #(length vs);
      True
    >>>.

  Lemma inf_queue_mpmc_1٠is_emptyspec t ι :
    <<<
      inf_queue_mpmc_1۰inv t ι
    | ∀∀ vs,
      inf_queue_mpmc_1۰model t vs
    >>>
      inf_queue_mpmc_1٠is_empty t @ ι
    <<<
      inf_queue_mpmc_1۰model t vs
    | RET #(bool_decide (vs = []%list));
      True
    >>>.

  Lemma inf_queue_mpmc_1٠is_empty_weakspec t ι :
    <<<
      inf_queue_mpmc_1۰inv t ι
    | ∀∀ vs,
      inf_queue_mpmc_1۰model t vs
    >>>
      inf_queue_mpmc_1٠is_empty_weak t @ ι
    <<<
      ∃∃ b,
      if b then vs = [] else True
      inf_queue_mpmc_1۰model t vs
    | RET #b;
      True
    >>>.

  Lemma inf_queue_mpmc_1٠pushspec t ι v :
    <<<
      inf_queue_mpmc_1۰inv t ι
    | ∀∀ vs,
      inf_queue_mpmc_1۰model t vs
    >>>
      inf_queue_mpmc_1٠push t v @ ι
    <<<
      inf_queue_mpmc_1۰model t (vs ++ [v])
    | RET ();
      True
    >>>.

  Lemma inf_queue_mpmc_1٠popspec t ι :
    <<<
      inf_queue_mpmc_1۰inv t ι
    | ∀∀ vs,
      inf_queue_mpmc_1۰model t vs
    >>>
      inf_queue_mpmc_1٠pop t @ ι
    <<<
      ∃∃ v vs',
      vs = v :: vs'
      inf_queue_mpmc_1۰model t vs'
    | RET v;
      True
    >>>.

  Lemma inf_queue_mpmc_1٠try_popspec t ι :
    <<<
      inf_queue_mpmc_1۰inv t ι
    | ∀∀ vs,
      inf_queue_mpmc_1۰model t vs
    >>>
      inf_queue_mpmc_1٠try_pop t @ ι
    <<<
      inf_queue_mpmc_1۰model t (tail vs)
    | RET head vs;
      True
    >>>.
End inf_queue_mpmc_1۰G.

#[global] Opaque inf_queue_mpmc_1۰inv.
#[global] Opaque inf_queue_mpmc_1۰model.