Library zoo_saturn.inf_queue_mpmc_2

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.common.function.
Require Import zoo.common.list.
Require Import zoo.common.relations.
Require Import zoo.iris.bi.big_op.
Require Import zoo.iris.base_logic.lib.twins.
Require Import zoo.iris.base_logic.lib.auth_mono.
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_identifier.
Require Import zoo.program_logic.prophet_multi.
Require Import zoo.program_logic.prophet_nat.
Require Export zoo_saturn.inf_queue_mpmc_2__code.
Require Import zoo_saturn.inf_queue_mpmc_2__types.
Require Import zoo.options.

Implicit Type b : bool.
Implicit Type front back : nat.
Implicit Type v : val.
Implicit Type o : option val.
Implicit Type vs : list val.
Implicit Type hist : list (option val).
Implicit Type slot : optional val.
Implicit Type slots : nat optional val.
Implicit Type η : gname.
Implicit Type ηs : list gname.
Implicit Type past prophs : list prophet_identifier.(prophet_typed۰type).
Implicit Type pasts prophss : nat list prophet_identifier.(prophet_typed۰type).

Variant lstate :=
  | Producer
  | ProducerProducer
  | ProducerConsumer
  | Consumer
  | ConsumerProducer η
  | ConsumerConsumer.
#[local] Canonical lstate۰O {SI : sidx} :=
  leibnizO lstate.
Implicit Type lstate : lstate.
Implicit Type lstates : list lstate.

#[local] Definition lstate۰winner lstate :=
  match lstate with
  | Producer
      Producer
  | ProducerProducer
      Producer
  | ProducerConsumer
      Consumer
  | Consumer
      Consumer
  | ConsumerProducer η
      Producer
  | ConsumerConsumer
      Consumer
  end.

#[local] Definition lstate۰measure lstate :=
  match lstate with
  | Producer
  | Consumer
      0
  | ProducerProducer
  | ProducerConsumer
  | ConsumerProducer _
  | ConsumerConsumer
      1
  end.

Variant lstep : lstate lstate Prop :=
  | lstepproducerproducer :
      lstep Producer ProducerProducer
  | lstepproducerconsumer :
      lstep Consumer ProducerConsumer
  | lstepconsumerproducer η :
      lstep Producer (ConsumerProducer η)
  | lstepconsumerconsumer :
      lstep Consumer ConsumerConsumer.

#[local] Lemma lstepmeasure lstate1 lstate2 :
  lstep lstate1 lstate2
  lstate۰measure lstate1 < lstate۰measure lstate2.
#[local] Lemma lsteptcmeasure lstate1 lstate2 :
  tc lstep lstate1 lstate2
  lstate۰measure lstate1 < lstate۰measure lstate2.
#[local] Lemma lsteprtcmeasure lstate1 lstate2 :
  rtc lstep lstate1 lstate2
  lstate۰measure lstate1 lstate۰measure lstate2.

#[local] Instance lstepsantisymm :
  AntiSymm (=) (rtc lstep).

#[local] Lemma lstate۰winnerlb lstate :
  rtc lstep (lstate۰winner lstate) lstate.
#[local] Lemma lstepwinner lstate1 lstate2 :
  lstep lstate1 lstate2
  lstate۰winner lstate1 = lstate۰winner lstate2.
#[local] Lemma lstepswinner lstate1 lstate2 :
  rtc lstep lstate1 lstate2
  lstate۰winner lstate1 = lstate۰winner lstate2.

Class InfQueueMpmc2G Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] inf_queue_mpmc_2۰G۰inf_array۰G :: InfArrayG Σ
  ; #[local] inf_queue_mpmc_2۰G۰prophet۰G :: ProphetMultiG Σ prophet_identifier
  ; #[local] inf_queue_mpmc_2۰G۰model۰G :: TwinsG Σ (leibnizO (list val))
  ; #[local] inf_queue_mpmc_2۰G۰history۰G :: MonoListG Σ (option val)
  ; #[local] inf_queue_mpmc_2۰G۰lstate۰G :: AuthMonoG Σ lstep
  ; #[local] inf_queue_mpmc_2۰G۰lstates۰G :: MonoListG Σ gname
  ; #[local] inf_queue_mpmc_2۰G۰saved_pred۰G :: SavedPredG Σ val
  ; #[local] inf_queue_mpmc_2۰G۰producer۰G :: OneshotG Σ () ()
  ; #[local] inf_queue_mpmc_2۰G۰producers۰G :: MonoListG Σ gname
  ; #[local] inf_queue_mpmc_2۰G۰consumer۰G :: OneshotG Σ () ()
  ; #[local] inf_queue_mpmc_2۰G۰consumers۰G :: MonoListG Σ gname
  }.

Definition inf_queue_mpmc_2۰Σ :=
  #[inf_array۰Σ
  ; prophet_multi۰Σ prophet_identifier
  ; twins۰Σ (leibnizO (list val))
  ; mono_list۰Σ (option val)
  ; mono_list۰Σ gname
  ; auth_mono۰Σ lstep
  ; saved_pred۰Σ val
  ; oneshot۰Σ () ()
  ; mono_list۰Σ gname
  ; oneshot۰Σ () ()
  ; mono_list۰Σ gname
  ].
#[global] Instance subGinf_queue_mpmc_2۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG inf_queue_mpmc_2۰Σ Σ
  InfQueueMpmc2G Σ.

Module base.
  Section inf_queue_mpmc_2۰G.
    Context `{inf_queue_mpmc_2۰G : InfQueueMpmc2G Σ}.

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

    Record inf_queue_mpmc_2۰name :=
      { inf_queue_mpmc_2۰name۰data : val
      ; inf_queue_mpmc_2۰name۰inv : namespace
      ; inf_queue_mpmc_2۰name۰prophet : prophet_id
      ; inf_queue_mpmc_2۰name۰prophet_name : prophet_multi۰name
      ; inf_queue_mpmc_2۰name۰model : gname
      ; inf_queue_mpmc_2۰name۰history : gname
      ; inf_queue_mpmc_2۰name۰lstates : gname
      ; inf_queue_mpmc_2۰name۰producers : gname
      ; inf_queue_mpmc_2۰name۰consumers : gname
      }.
    Implicit Type γ : inf_queue_mpmc_2۰name.

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

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

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

    #[local] Definition lstates۰auth' γ_lstates lstates : iProp Σ :=
       ηs,
      mono_list۰auth γ_lstates (DfracOwn 1) ηs
      [∗ list] η; lstate ηs; lstates,
        auth_mono۰auth _ η DfracDiscarded lstate.
    #[local] Definition lstates۰auth γ :=
      lstates۰auth' γ.(inf_queue_mpmc_2۰name۰lstates).
    #[local] Instance : CustomIpat "lstates۰auth" :=
      " ( %ηs & Hauth & Hηs ) ".
    #[local] Definition lstates۰at γ i lstate : iProp Σ :=
       η,
      mono_list۰at γ.(inf_queue_mpmc_2۰name۰lstates) i η
      auth_mono۰auth _ η DfracDiscarded lstate.
    #[local] Instance : CustomIpat "lstates۰at" :=
      " ( %η{} & #Hat{_{}} & #Hη_auth{_{}} ) ".
    #[local] Definition lstates۰lb γ i lstate : iProp Σ :=
       η,
      mono_list۰at γ.(inf_queue_mpmc_2۰name۰lstates) i η
      auth_mono۰lb _ η lstate.
    #[local] Instance : CustomIpat "lstates۰lb" :=
      " ( %η{} & #Hat{_{}} & #Hη_lb{_{}} ) ".

    #[local] Definition producers۰auth' γ_producers i : iProp Σ :=
       ηs,
      mono_list۰auth γ_producers (DfracOwn 1) ηs
      length ηs = i.
    #[local] Definition producers۰auth γ :=
      producers۰auth' γ.(inf_queue_mpmc_2۰name۰producers).
    #[local] Instance : CustomIpat "producers۰auth" :=
      " ( %ηs & Hauth & %Hηs ) ".
    #[local] Definition producers۰at γ i own : iProp Σ :=
       η,
      mono_list۰at γ.(inf_queue_mpmc_2۰name۰producers) i η
      match own with
      | Own
          oneshot۰pending η (DfracOwn 1) ()
      | Discard
          oneshot۰shot η ()
      end.
    #[local] Instance : CustomIpat "producers۰at" :=
      " ( %η{} & Hat{_{}} & Hη{} ) ".

    #[local] Definition consumers۰auth' γ_consumers i : iProp Σ :=
       ηs,
      mono_list۰auth γ_consumers (DfracOwn 1) ηs
      length ηs = i.
    #[local] Definition consumers۰auth γ :=
      consumers۰auth' γ.(inf_queue_mpmc_2۰name۰consumers).
    #[local] Instance : CustomIpat "consumers۰auth" :=
      " ( %ηs{} & Hauth{} & %Hηs{} ) ".
    #[local] Definition consumers۰at γ i own : iProp Σ :=
       η,
      mono_list۰at γ.(inf_queue_mpmc_2۰name۰consumers) i η
      match own with
      | Own
          oneshot۰pending η (DfracOwn 1) ()
      | Discard
          oneshot۰shot η ()
      end.
    #[local] Instance : CustomIpat "consumers۰at" :=
      " ( %η{} & Hat{_{}} & Hη{} ) ".
    #[local] Definition consumers۰lb γ i : iProp Σ :=
       ηs,
      mono_list۰lb γ.(inf_queue_mpmc_2۰name۰consumers) ηs
      length ηs = i.
    #[local] Instance : CustomIpat "consumers۰lb" :=
      " ( %ηs{} & Hlb{} & %Hηs{} ) ".

    #[local] Definition winner γ i : iProp Σ :=
       id prophs,
      prophet_multi۰full prophet_identifier γ.(inf_queue_mpmc_2۰name۰prophet_name) i prophs
      head prophs = Some id
      identifier۰model id.
    #[local] Instance : CustomIpat "winner" :=
      " ( %id{} & %prophs{} & Hprophet_full{_{}} & %Hprophs{} & Hid{} ) ".

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

    #[local] Definition inv۰lstate۰left γ back i lstate : iProp Σ :=
      match lstate with
      | ProducerProducer
           v,
          history۰at γ i (Some v)
          winner γ i
      | ProducerConsumer
          history۰at γ i None
      | ConsumerProducer η
           Ψ v,
          consumers۰lb γ ˖i
          saved_pred η Ψ
          history۰at γ i (Some v)
          ( Ψ v
           consumers۰at γ i Discard
          )
      | ConsumerConsumer
          consumers۰lb γ ˖i
      | _
          False
      end.
    #[local] Instance : CustomIpat "inv۰lstate۰left۰producer" :=
      " ( %v & #Hhistory_at & Hwinner ) ".
    #[local] Instance : CustomIpat "inv۰lstate۰left۰consumer" :=
      " ( %Ψ & %v_ & #Hconsumers_lb & #Hη_ & #Hhistory_at_ & HΨ ) ".

    #[local] Definition inv۰lstate۰right γ i lstate : iProp Σ :=
      match lstate with
      | ConsumerProducer η
           Ψ,
          saved_pred η Ψ
          consumer۰au γ Ψ
      | ConsumerConsumer
          winner γ i
      | _
          False
      end.
    #[local] Instance : CustomIpat "inv۰lstate۰right" :=
      " ( %Ψ & #Hη & Hconsumer_au ) ".

    #[local] Definition inv۰slot γ i slot past : iProp Σ :=
      match slot with
      | Nothing
          past = []
      | Something v
          history۰at γ i (Some v)
          producers۰at γ i Discard
          lstates۰lb γ i Producer
      | Anything
          consumers۰at γ i Discard
          ( lstates۰lb γ i Consumer
           producers۰at γ i Discard
          )
      end.
    #[local] Instance : CustomIpat "inv۰slot۰nothing" :=
      " %Hpast ".
    #[local] Instance : CustomIpat "inv۰slot۰something" :=
      " ( #Hhistory_at{_{suff}} & #Hproducers_at{_{suff}} & #Hlstates_lb_producer ) ".
    #[local] Instance : CustomIpat "inv۰slot۰anything" :=
      " ( #Hconsumers_at{_{suff}} & { _{suff} ; [ #Hlstates_lb_consumer | #Hproducers_at_ ] } ) ".

    #[local] Definition inv۰inner t γ : iProp Σ :=
       front back hist slots vs lstates pasts prophss,
      t.[front] #front
      t.[back] #back
      inf_array۰model γ.(inf_queue_mpmc_2۰name۰data) slots
      model₂ γ vs
      vs = oflatten (drop front hist)
      history۰auth γ hist
      length hist = back
      lstates۰auth γ lstates
      length lstates = front `max` back
      prophet_multi۰model prophet_identifier γ.(inf_queue_mpmc_2۰name۰prophet) γ.(inf_queue_mpmc_2۰name۰prophet_name) pasts prophss
      producers۰auth γ back
      consumers۰auth γ front
      ( [∗ list] i lstate take back lstates,
        inv۰lstate۰left γ back i lstate
      )
      ( [∗ list] k lstate drop back lstates,
        inv۰lstate۰right γ (back + k) lstate
      )
      ( i,
        inv۰slot γ i (slots i) (pasts i)
      ).
    #[local] Instance : CustomIpat "inv۰inner" :=
      " ( %front{} & %back{} & %hist{} & %slots{} & %vs{} & %lstates{} & %pasts{} & %prophss{} & Ht_front & Ht_back & >Hdata_model & Hmodel₂ & >%Hvs{} & Hhistory_auth & >%Hhist{} & Hlstates_auth & >%Hlstates{} & >Hprophet_model & Hproducers_auth & Hconsumers_auth & Hlstates_left & Hlstates_right & Hslots ) ".
    Definition inf_queue_mpmc_2۰inv t γ ι : iProp Σ :=
      ι = γ.(inf_queue_mpmc_2۰name۰inv)
      t.[data] γ.(inf_queue_mpmc_2۰name۰data)
      t.[proph] #γ.(inf_queue_mpmc_2۰name۰prophet)
      inf_array۰inv γ.(inf_queue_mpmc_2۰name۰data)
      inv γ.(inf_queue_mpmc_2۰name۰inv) (inv۰inner t γ).
    #[local] Instance : CustomIpat "inv" :=
      " ( -> & #Ht_data & #Ht_proph & #Hdata_inv & #Hinv ) ".

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

    #[global] Instance inf_queue_mpmc_2۰modeltimeless γ vs :
      Timeless (inf_queue_mpmc_2۰model γ vs).

    #[local] Instance lstates۰atpersistent γ i lstate :
      Persistent (lstates۰at γ i lstate).
    #[local] Instance lstates۰lbpersistent γ i lstate :
      Persistent (lstates۰lb γ i lstate).
    #[local] Instance producers۰atpersistent γ i :
      Persistent (producers۰at γ i Discard).
    #[local] Instance consumers۰atpersistent γ i :
      Persistent (consumers۰at γ i Discard).
    #[local] Instance consumers۰lbpersistent γ i :
      Persistent (consumers۰lb γ i).
    #[local] Instance inv۰slotpersistent γ i slot past :
      Persistent (inv۰slot γ i slot past).
    #[global] Instance inf_queue_mpmc_2۰invpersistent t γ ι :
      Persistent (inf_queue_mpmc_2۰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۰atlookup γ hist i o :
      history۰auth γ hist -∗
      history۰at γ i o -∗
      hist !! i = Some o.
    #[local] Lemma history۰atagree γ i o1 o2 :
      history۰at γ i o1 -∗
      history۰at γ i o2 -∗
      o1 = o2.
    #[local] Lemma history۰atget {γ hist} i o :
      hist !! i = Some o
      history۰auth γ hist
      history۰at γ i o.
    #[local] Lemma historyupdate {γ hist} o :
      history۰auth γ hist |==>
        history۰auth γ (hist ++ [o])
        history۰at γ (length hist) o.

    #[local] Lemma lstatesalloc :
       |==>
         γ_lstates,
        lstates۰auth' γ_lstates [].
    #[local] Lemma lstates۰atlookup γ lstates i lstate :
      lstates۰auth γ lstates -∗
      lstates۰at γ i lstate -∗
      lstates !! i = Some lstate.
    #[local] Lemma lstates۰lbget {γ lstates} i lstate :
      lstates !! i = Some lstate
      lstates۰auth γ lstates -∗
      lstates۰lb γ i (lstate۰winner lstate).
    #[local] Lemma lstates۰lbagree γ i lstate1 lstate2 :
      lstates۰lb γ i lstate1 -∗
      lstates۰lb γ i lstate2 -∗
      lstate۰winner lstate1 = lstate۰winner lstate2.
    #[local] Lemma lstatesupdate {γ lstates} lstate :
      lstates۰auth γ lstates |==>
        lstates۰auth γ (lstates ++ [lstate])
        lstates۰lb γ (length lstates) (lstate۰winner lstate)
        lstates۰at γ (length lstates) lstate.
    Opaque lstates۰auth'.
    Opaque lstates۰at.
    Opaque lstates۰lb.

    #[local] Lemma producersalloc :
       |==>
         γ_producers,
        producers۰auth' γ_producers 0.
    #[local] Lemma producers۰atexclusive γ i own :
      producers۰at γ i Own -∗
      producers۰at γ i own -∗
      False.
    #[local] Lemma producers۰atdiscard γ i :
      producers۰at γ i Own |==>
      producers۰at γ i Discard.
    #[local] Lemma producersupdate γ i :
      producers۰auth γ i |==>
        producers۰auth γ ˖i
        producers۰at γ i Own.
    Opaque producers۰auth'.
    Opaque producers۰at.

    #[local] Lemma consumersalloc :
       |==>
         γ_consumers,
        consumers۰auth' γ_consumers 0.
    #[local] Lemma consumers۰atexclusive γ i own :
      consumers۰at γ i Own -∗
      consumers۰at γ i own -∗
      False.
    #[local] Lemma consumers۰atdiscard γ i :
      consumers۰at γ i Own |==>
      consumers۰at γ i Discard.
    #[local] Lemma consumers۰lbvalid γ i j :
      consumers۰auth γ i -∗
      consumers۰lb γ j -∗
      j i.
    #[local] Lemma consumers۰lble {γ i1} i2 :
      i2 i1
      consumers۰lb γ i1
      consumers۰lb γ i2.
    #[local] Lemma consumers۰lbget γ i :
      consumers۰auth γ i
      consumers۰lb γ i.
    #[local] Lemma consumers۰lbget' {γ i} i' :
      i' i
      consumers۰auth γ i
      consumers۰lb γ i'.
    #[local] Lemma consumersupdate γ i :
      consumers۰auth γ i |==>
        consumers۰auth γ ˖i
        consumers۰at γ i Own.
    Opaque consumers۰auth'.
    Opaque consumers۰at.
    Opaque consumers۰lb.

    #[local] Lemma winnerexclusive γ i :
      winner γ i -∗
      winner γ i -∗
      False.

    #[local] Lemma inv۰slotnotnothingpast {γ i slot past1} past2 :
      slot Nothing
      inv۰slot γ i slot past1 ⊣⊢
      inv۰slot γ i slot past2.

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

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

    Lemma inf_queue_mpmc_2٠sizespec t γ ι :
      <<<
        inf_queue_mpmc_2۰inv t γ ι
      | ∀∀ vs,
        inf_queue_mpmc_2۰model γ vs
      >>>
        inf_queue_mpmc_2٠size #t @ ι
      <<<
        inf_queue_mpmc_2۰model γ vs
      | sz,
        RET #sz;
        length vs sz
      >>>.

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

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

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

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

Require zoo_saturn.inf_queue_mpmc_2__opaque.

Section inf_queue_mpmc_2۰G.
  Context `{inf_queue_mpmc_2۰G : InfQueueMpmc2G Σ}.

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

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

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

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

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

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

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

  Lemma inf_queue_mpmc_2٠sizespec t ι :
    <<<
      inf_queue_mpmc_2۰inv t ι
    | ∀∀ vs,
      inf_queue_mpmc_2۰model t vs
    >>>
      inf_queue_mpmc_2٠size t @ ι
    <<<
      inf_queue_mpmc_2۰model t vs
    | sz,
      RET #sz;
      length vs sz
    >>>.

  Lemma inf_queue_mpmc_2٠is_emptyspec t ι :
    <<<
      inf_queue_mpmc_2۰inv t ι
    | ∀∀ vs,
      inf_queue_mpmc_2۰model t vs
    >>>
      inf_queue_mpmc_2٠is_empty t @ ι
    <<<
      inf_queue_mpmc_2۰model t vs
    | b,
      RET #b;
      if b then vs = [] else True
    >>>.

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

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

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