Library zoo_parabs.pool

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.common.gmultiset.
Require Import zoo.iris.bi.big_op.
Require Import zoo.iris.base_logic.lib.ghost_list.
Require Import zoo.iris.base_logic.lib.mono_gmultiset.
Require Import zoo.iris.base_logic.lib.saved_prop.
Require Import zoo.iris.base_logic.lib.prop_spsc.
Require Import zoo.base.
Require Export zoo_parabs.base.
Require Export zoo_parabs.pool__code.
Require Import zoo_parabs.pool__types.
Require Import zoo.options.

Implicit Type b : bool.
Implicit Type v ctx hub task notification notify pred ivar waiter : val.
Implicit Type empty : emptiness.
Implicit Type own : ownership.
Implicit Type η : prop_spsc۰name.
Implicit Type ω : gname.

#[local] Definition max_round_noyield :=
  val۰to_nat' pool٠max_round_noyield.
#[local] Lemma pool٠max_round_noyieldunfold :
  pool٠max_round_noyield = #max_round_noyield.
Opaque pool٠max_round_noyield.
Opaque max_round_noyield.

#[local] Definition max_round_yield :=
  val۰to_nat' pool٠max_round_yield.
#[local] Lemma pool٠max_round_yieldunfold :
  pool٠max_round_yield = #max_round_yield.
Opaque pool٠max_round_yield.
Opaque max_round_yield.

Record job :=
  { job۰val : val
  ; job۰name : gname
  }.
Implicit Type job local global : job.

#[local] Instance jobinhabited : Inhabited job :=
  populate
  {|job۰val := inhabitant
  ; job۰name := inhabitant
  |}.
#[local] Instance jobeq_dec : EqDecision job :=
  ltac:(solve_decision).
#[local] Instance jobcountable :
  Countable job.

Implicit Type jobs locals ulocals globals : gmultiset job.
Implicit Type localss : list $ gmultiset job.

Definition pool۰scope :=
  gmultiset job.

#[global] Instance pool۰scopeeq_dec : EqDecision pool۰scope :=
  _.
#[global] Instance pool۰scopecountable :
  Countable pool۰scope.

Class PoolG Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] pool۰G۰domain۰G :: DomainG Σ
  ; #[local] pool۰G۰ws_hub۰G :: WsHubStdG Σ
  ; #[local] pool۰G۰saved_prop۰G :: SavedPropG Σ
  ; #[local] pool۰G۰jobs۰G :: MonoGmultisetG Σ job
  ; #[local] pool۰G۰locals۰G :: GhostListG Σ (gmultiset job)
  ; #[local] pool۰G۰consumer۰G :: PropSpscG Σ
  }.

Definition pool۰Σ :=
  #[domain۰Σ
  ; ws_hub_std۰Σ
  ; saved_prop۰Σ
  ; mono_gmultiset۰Σ job
  ; ghost_list۰Σ (gmultiset job)
  ; prop_spsc۰Σ
  ].
#[global] Instance subGpool۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG pool۰Σ Σ
  PoolG Σ.

Module base.
  Section pool۰G.
    Context `{pool۰G : PoolG Σ}.

    Implicit Type t : location.
    Implicit Type P P_notification P_pred Q Q_pred : iProp Σ.
    Implicit Type Ψ : val iProp Σ.

    Record pool۰name :=
      { pool۰name۰size : nat
      ; pool۰name۰hub : val
      ; pool۰name۰domains : val
      ; pool۰name۰jobs : gname
      ; pool۰name۰locals : gname
      }.
    Implicit Type γ : pool۰name.
    Implicit Type γ_tokens : list gname.

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

    #[local] Definition pool۰name۰context γ (i : nat) :=
      ( #γ.(pool۰name۰size),
        γ.(pool۰name۰hub),
        #i
      )%V.
    #[local] Instance pool۰name۰contextinj γ :
      Inj (=) (=) (pool۰name۰context γ).

    #[local] Definition jobs۰auth' γ_jobs own :=
      mono_gmultiset۰auth γ_jobs own.
    #[local] Definition jobs۰auth γ :=
      jobs۰auth' γ.(pool۰name۰jobs).
    #[local] Definition jobs۰elem γ :=
      mono_gmultiset۰elem γ.(pool۰name۰jobs).

    #[local] Definition jobs۰finished jobs : iProp Σ :=
      [∗ mset] job jobs,
         P,
        saved_prop job.(job۰name) P
         P.

    #[local] Definition locals۰auth' sz γ_locals ulocals : iProp Σ :=
       localss,
      length localss = ˖sz
      ghost_list۰auth γ_locals localss
      ulocals = ⋃+ localss.
    #[local] Definition locals۰auth γ :=
      locals۰auth' γ.(pool۰name۰size) γ.(pool۰name۰locals).
    #[local] Instance : CustomIpat "locals۰auth" :=
      " ( %localss{} & %Hlocalss{} & Hauth{_{}} & -> ) ".
    #[local] Definition locals۰at۰running γ_locals i scope : iProp Σ :=
       locals,
      ghost_list۰at γ_locals i Own (scope locals)
      jobs۰finished locals.
    #[local] Instance : CustomIpat "locals۰at۰running" :=
      " ( %locals{} & Hat{_{}} & Hjobs_finished_locals{} ) ".
    #[local] Definition locals۰at۰finished γ_locals i : iProp Σ :=
       locals,
      ghost_list۰at γ_locals i Own locals.
    #[local] Instance : CustomIpat "locals۰at۰finished" :=
      " ( %locals{} & Hat{_{}} ) ".
    #[local] Definition locals۰at' γ_locals i scope : iProp Σ :=
      match scope with
      | Some scope
          locals۰at۰running γ_locals i scope
      | None
          locals۰at۰finished γ_locals i
      end.
    #[local] Definition locals۰at γ :=
      locals۰at' γ.(pool۰name۰locals).

    #[local] Definition globals۰model۰running γ globals : iProp Σ :=
       jobs ulocals,
      jobs = globals ulocals
      jobs۰auth γ Own jobs
      locals۰auth γ ulocals.
    #[local] Instance : CustomIpat "globals۰model۰running" :=
      " ( %jobs & %ulocals & -> & Hjobs_auth & Hlocals_auth ) ".
    #[local] Definition globals۰model۰finished γ : iProp Σ :=
      [∗ list] i seq 0 ˖(γ.(pool۰name۰size)),
        locals۰at γ i None.
    #[local] Instance : CustomIpat "globals۰model۰finished" :=
      " Hlocals_ats ".
    #[local] Definition globals۰model γ globals : iProp Σ :=
        globals۰model۰running γ globals
       globals۰model۰finished γ.
    #[local] Instance : CustomIpat "globals۰model" :=
      " [ (:globals۰model۰running) | (:globals۰model۰finished) ] ".

    #[local] Definition context₁ γ i (scope : pool۰scope) : iProp Σ :=
       empty,
      ws_hub_std۰owner γ.(pool۰name۰hub) i Nonblocked empty
      locals۰at γ i (Some scope).
    #[local] Instance : CustomIpat "context₁" :=
      " ( %empty{} & Hhub_owner{_{}} & Hlocals_at{_{}} ) ".

    #[local] Definition task۰model γ task Ψ : iProp Σ :=
       i scope,
      i γ.(pool۰name۰size) -∗
      context₁ γ i scope -∗
      WP task (pool۰name۰context γ i) {{ v,
        context₁ γ i scope
        Ψ v
      }}.

    #[local] Definition inv۰inner γ : iProp Σ :=
       globals 𝑔𝑙𝑜𝑏𝑎𝑙𝑠,
      𝑔𝑙𝑜𝑏𝑎𝑙𝑠 = gmultiset_map job۰val globals
      globals۰model γ globals
      ws_hub_std۰model γ.(pool۰name۰hub) 𝑔𝑙𝑜𝑏𝑎𝑙𝑠
      [∗ mset] global globals,
        task۰model γ global.(job۰val) (λ _,
           P,
          saved_prop global.(job۰name) P
           P
        ).
    #[local] Instance : CustomIpat "inv۰inner" :=
      " ( %globals & %𝑔𝑙𝑜𝑏𝑎𝑙𝑠 & >%H𝑔𝑙𝑜𝑏𝑎𝑙𝑠 & >Hglobals_model & >Hhub_model & Hglobals ) ".
    #[local] Definition inv₁ γ : iProp Σ :=
      inv (nroot.@"inv") (inv۰inner γ).
    #[local] Definition inv₂ γ : iProp Σ :=
      ws_hub_std۰inv γ.(pool۰name۰hub) (nroot.@"hub") ˖(γ.(pool۰name۰size))
      inv₁ γ.
    #[local] Instance : CustomIpat "inv₂" :=
      " ( #Hhub_inv{_{}} & #Hinv{_{}} ) ".
    Definition pool۰inv γ sz : iProp Σ :=
      sz = γ.(pool۰name۰size)
      inv₂ γ.
    #[local] Instance : CustomIpat "inv" :=
      " ( -> & {#Hinv_{};(:inv₂)} ) ".

    #[local] Definition context۰finished γ i : iProp Σ :=
      ws_hub_std۰owner γ.(pool۰name۰hub) i Nonblocked Empty
      locals۰at γ i (Some ).
    #[local] Instance : CustomIpat "context۰finished" :=
      " ( Hhub_owner{_{}} & Hlocals_at{_{}} ) ".
    #[local] Definition context₂ γ i scope : iProp Σ :=
      i γ.(pool۰name۰size)
      inv₂ γ
      context₁ γ i scope.
    #[local] Instance : CustomIpat "context₂" :=
      " ( %Hi{} & {#Hinv_{};(:inv₂)} & { {lazy} Hctx{} ; {lazy} Hctx ; (:context₁ ={}) ; (:context₁) } ) ".
    Definition pool۰context γ ctx scope : iProp Σ :=
       i,
      ctx = pool۰name۰context γ i
      context₂ γ i scope.
    #[local] Instance : CustomIpat "context" :=
      " ( %i{} & {%Heq{};->} & (:context₂) ) ".

    #[local] Definition worker۰post γ i res : iProp Σ :=
      res = ()%V
      context۰finished γ i.
    #[local] Instance : CustomIpat "worker۰post" :=
      " ( -> & (:context۰finished) ) ".

    Definition pool۰model t γ : iProp Σ :=
       empty doms,
      length doms = γ.(pool۰name۰size)
      t.[size] #γ.(pool۰name۰size)
      t.[hub] γ.(pool۰name۰hub)
      t.[domains] γ.(pool۰name۰domains)
      inv₂ γ
      array۰model γ.(pool۰name۰domains) DfracDiscarded doms
      ( [∗ list] i dom doms,
        domain۰model dom (worker۰post γ ˖i)
      )
      ws_hub_std۰owner γ.(pool۰name۰hub) 0 Blocked empty
      locals۰at γ 0 (Some ).
    #[local] Instance : CustomIpat "model" :=
      " ( %empty{} & %doms{} & %Hdoms{} & #Hl{}_size & #Hl{}_hub & #Hl{}_domains & {#Hinv{};(:inv₂)} & Hdomains{} & Hdoms{} & Hhub{}_owner & Hlocals_at{_{}} ) ".

    Definition pool۰finished γ : iProp Σ :=
       jobs,
      jobs۰auth γ Discard jobs
      jobs۰finished jobs.
    #[local] Instance : CustomIpat "finished" :=
      " ( %jobs{} & Hjobs_auth{_{}} & Hjobs_finished{_jobs{}} ) ".

    Definition pool۰consumer γ P : iProp Σ :=
      pool۰finished γ ={}=∗
      P.

    Definition pool۰obligation γ P : iProp Σ :=
       (
        pool۰finished γ -∗
         P
      ).

    #[global] Instance pool۰obligationproper γ :
      Proper ((≡) ==> (≡)) (pool۰obligation γ).
    #[global] Instance pool۰consumerproper γ :
      Proper ((≡) ==> (≡)) (pool۰consumer γ).

    #[local] Instance globals۰modeltimeless γ globals :
      Timeless (globals۰model γ globals).

    #[local] Instance jobs۰elempersistent γ job :
      Persistent (jobs۰elem γ job).
    #[local] Instance jobs۰finishedpersistent jobs :
      Persistent (jobs۰finished jobs).
    #[global] Instance pool۰invpersistent γ sz :
      Persistent (pool۰inv γ sz).
    #[global] Instance pool۰obligationpersistent γ P :
      Persistent (pool۰obligation γ P).
    #[global] Instance pool۰finishedpersistent γ :
      Persistent (pool۰finished γ).

    #[local] Lemma jobsalloc :
       |==>
         γ_jobs,
        jobs۰auth' γ_jobs Own .
    #[local] Lemma jobs۰authdiscard γ jobs :
      jobs۰auth γ Own jobs |==>
      jobs۰auth γ Discard jobs.
    #[local] Lemma jobs۰elemvalid γ own jobs job :
      jobs۰auth γ own jobs -∗
      jobs۰elem γ job -∗
      job jobs.
    #[local] Lemma jobsinsert {γ jobs} 𝑗𝑜𝑏 P :
      jobs۰auth γ Own jobs |==>
         job,
        job.(job۰val) = 𝑗𝑜𝑏
        jobs۰auth γ Own ({[+job+]} jobs)
        jobs۰elem γ job
        saved_prop job.(job۰name) P.
    Opaque jobs۰elem.

    #[local] Lemma jobs۰finishedempty :
       jobs۰finished .
    #[local] Lemma jobs۰finishedelem_of job jobs :
      job jobs
      jobs۰finished jobs
         P,
        saved_prop job.(job۰name) P
         P.
    #[local] Lemma jobs۰finishedinsert {jobs} job P :
      jobs۰finished jobs -∗
      saved_prop job.(job۰name) P -∗
       P -∗
      jobs۰finished ({[+job+]} jobs).
    #[local] Lemma jobs۰finishedunion localss :
      ( [∗ list] locals localss,
        jobs۰finished locals
      )
      jobs۰finished (⋃+ localss).
    Opaque jobs۰finished.

    #[local] Lemma localsalloc sz :
       |==>
         γ_locals,
        locals۰auth' sz γ_locals
        [∗ list] i seq 0 ˖sz,
          locals۰at' γ_locals i (Some ).
    #[local] Lemma locals۰atexclusive γ i scope1 scope2 :
      locals۰at γ i scope1 -∗
      locals۰at γ i scope2 -∗
      False.
    #[local] Lemma localsinsert {γ ulocals i scope} local :
      locals۰auth γ ulocals -∗
      locals۰at γ i (Some scope) ==∗
        locals۰auth γ ({[+local+]} ulocals)
        locals۰at γ i (Some ({[+local+]} scope)).
    #[local] Lemma locals۰atfinish γ i local P scope :
      locals۰at γ i (Some ({[+local+]} scope)) -∗
      saved_prop local.(job۰name) P -∗
       P -∗
      locals۰at γ i (Some scope).
    #[local] Lemma localsclose γ ulocals :
      locals۰auth γ ulocals -∗
      ( [∗ list] i seq 0 ˖(γ.(pool۰name۰size)),
        locals۰at γ i (Some )
      ) -∗
        locals۰auth γ ulocals
        ( [∗ list] i seq 0 ˖(γ.(pool۰name۰size)),
          locals۰at γ i None
        )
        jobs۰finished ulocals.
    Opaque locals۰auth'.
    Opaque locals۰at'.

    #[local] Lemma globals۰modelinit γ :
      jobs۰auth γ Own -∗
      locals۰auth γ -∗
      globals۰model γ .
    #[local] Lemma globals۰modellocals۰at γ globals i scope :
      i γ.(pool۰name۰size)
      globals۰model γ globals -∗
      locals۰at γ i scope -∗
        globals۰model۰running γ globals
        locals۰at γ i scope.
    #[local] Lemma globals۰modelpush {γ globals} 𝑔𝑙𝑜𝑏𝑎𝑙 P i scope :
      i γ.(pool۰name۰size)
      globals۰model γ globals -∗
      locals۰at γ i scope ==∗
         global,
        global.(job۰val) = 𝑔𝑙𝑜𝑏𝑎𝑙
        globals۰model γ ({[+global+]} globals)
        locals۰at γ i scope
        jobs۰elem γ global
        saved_prop global.(job۰name) P.
    #[local] Lemma globals۰modelpop {γ globals} global globals' i scope :
      i γ.(pool۰name۰size)
      globals = {[+global+]} globals'
      globals۰model γ globals -∗
      locals۰at γ i (Some scope) ==∗
        globals۰model γ globals'
        locals۰at γ i (Some ({[+global+]} scope)).
    #[local] Lemma globals۰modelclose γ :
      globals۰model γ -∗
      ( [∗ list] i seq 0 ˖(γ.(pool۰name۰size)),
        locals۰at γ i (Some )
      ) ==∗
         jobs,
        globals۰model γ
        jobs۰auth γ Discard jobs
        jobs۰finished jobs.
    Opaque globals۰model.

    Lemma pool۰invagree γ sz1 sz2 :
      pool۰inv γ sz1 -∗
      pool۰inv γ sz2 -∗
      sz1 = sz2.

    Lemma pool۰obligationwand {γ P1} P2 :
      pool۰obligation γ P1 -∗
       (P1 -∗ P2) -∗
      pool۰obligation γ P2.
    Lemma pool۰obligationsplit γ P1 P2 :
      pool۰obligation γ (P1 P2)
        pool۰obligation γ P1
        pool۰obligation γ P2.
    Lemma pool۰obligationcombine γ P1 P2 :
      pool۰obligation γ P1 -∗
      pool۰obligation γ P2 -∗
      pool۰obligation γ (P1 P2).
    Lemma pool۰obligationfinished γ P :
      pool۰obligation γ P -∗
      pool۰finished γ -∗
       P.

    #[local] Lemma pool٠contextspec {sz : Z} {hub} {i : Z} γ (i_ : nat) :
      sz = γ.(pool۰name۰size)
      hub = γ.(pool۰name۰hub)
      i = i_
      {{{
        True
      }}}
        pool__code.pool٠context #sz hub #i
      {{{
        RET pool۰name۰context γ i_;
        True
      }}}.

    #[local] Lemma pool٠context_mainspec t γ :
      {{{
        t.[size] #γ.(pool۰name۰size)
        t.[hub] γ.(pool۰name۰hub)
      }}}
        pool٠context_main #t
      {{{
        RET pool۰name۰context γ 0;
        True
      }}}.

    #[local] Lemma pool٠executespec γ i scope task Ψ :
      i γ.(pool۰name۰size)
      {{{
        context₁ γ i scope
        task۰model γ task Ψ
      }}}
        pool٠execute (pool۰name۰context γ i) task
      {{{
        v
      , RET v;
        context₁ γ i scope
        Ψ v
      }}}.

    #[local] Lemma pool٠workerspec γ i :
      {{{
        context₂ γ i
      }}}
        pool٠worker (pool۰name۰context γ i)
      {{{
        res
      , RET res;
        worker۰post γ i res
      }}}.

    Lemma pool٠createspec sz :
      (0 sz)%Z
      {{{
        True
      }}}
        pool٠create #sz
      {{{
        t γ
      , RET #t;
        pool۰inv γ sz
        pool۰model t γ
        meta_token t
      }}}.

    Lemma pool٠run_onspec Ψ t γ task :
      {{{
        pool۰model t γ
        ( ctx scope,
          pool۰context γ ctx scope -∗
          WP task ctx {{ v,
            pool۰context γ ctx scope
            Ψ v
          }}
        )
      }}}
        pool٠run_on #t task
      {{{
        v
      , RET v;
        pool۰model t γ
        Ψ v
      }}}.

    Lemma pool٠closespec t γ :
      {{{
        pool۰model t γ
      }}}
        pool٠close #t
      {{{
        RET ();
        pool۰finished γ
      }}}.

    Lemma pool٠runspec (Ψ : location pool۰name val iProp Σ) sz task :
      (0 sz)%Z
      {{{
         t γ ctx scope,
        pool۰inv γ sz -∗
        meta_token t -∗
        pool۰context γ ctx scope -∗
        WP task ctx {{ v,
          pool۰context γ ctx scope
          Ψ t γ v
        }}
      }}}
        pool٠run #sz task
      {{{
        t γ v
      , RET v;
        pool۰finished γ
        Ψ t γ v
      }}}.

    Lemma pool٠sizespec γ sz ctx scope :
      {{{
        pool۰inv γ sz
        pool۰context γ ctx scope
      }}}
        pool٠size ctx
      {{{
        RET #sz;
        pool۰context γ ctx scope
      }}}.

    Lemma pool٠asyncspec P Q γ ctx scope task :
      {{{
        pool۰context γ ctx scope
        ( ctx scope,
          pool۰context γ ctx scope -∗
          WP task ctx {{ res,
            pool۰context γ ctx scope
             P
             Q
          }}
        )
      }}}
        pool٠async ctx task
      {{{
        RET ();
        pool۰context γ ctx scope
        pool۰consumer γ P
        pool۰obligation γ Q
      }}}.

    #[local] Lemma pool٠wait₁spec P_notification P_pred Q_pred γ ctx scope notification pred :
      {{{
        pool۰context γ ctx scope
        P_notification
         (
           notify,
          P_notification -∗
          WP notify () {{ itype۰unit }} -∗
          WP notification notify {{ res,
            res = ()%V
            P_notification
          }}
        )
        P_pred
         (
          P_pred -∗
          WP pred () {{ res,
             b,
            res = #b
            if b then Q_pred else P_pred
          }}
        )
      }}}
        pool٠wait₁ ctx notification pred
      {{{
        RET ();
        pool۰context γ ctx scope
        Q_pred
      }}}.

    Lemma pool٠waitspec P_notification P_pred Q_pred γ ctx scope notification pred :
      {{{
        pool۰context γ ctx scope
        P_notification
        ( notify,
          P_notification -∗
          WP notify () {{ itype۰unit }} -∗
          WP notification notify {{ res,
            res = ()%V
            P_notification
          }}
        )
        P_pred
         (
          P_pred -∗
          WP pred () {{ res,
             b,
            res = #b
            if b then Q_pred else P_pred
          }}
        )
      }}}
        pool٠wait ctx notification pred
      {{{
        RET ();
        pool۰context γ ctx scope
        Q_pred
      }}}.

    Lemma pool٠wait_ivarspec `{ivar۰G : !Ivar4G Σ} {context_name} γ ctx scope ivar Ψ Ξ (Γ : _ context_name _) :
      {{{
        pool۰context γ ctx scope
        ivar_4۰inv ivar Ψ Ξ Γ
      }}}
        pool٠wait_ivar ctx ivar
      {{{
        RET ();
        £ 2
        pool۰context γ ctx scope
        ivar_4۰resolved ivar
      }}}.
  End pool۰G.

  #[global] Opaque pool۰scope.
  #[global] Opaque pool۰inv.
  #[global] Opaque pool۰model.
  #[global] Opaque pool۰context.
  #[global] Opaque pool۰consumer.
  #[global] Opaque pool۰obligation.
  #[global] Opaque pool۰finished.
End base.

Require zoo_parabs.pool__opaque.

Section pool۰G.
  Context `{pool۰G : PoolG Σ}.

  Implicit Type 𝑡 : location.
  Implicit Type t : val.
  Implicit Type γ : base.pool۰name.
  Implicit Type P P_notification P_pred Q Q_pred : iProp Σ.
  Implicit Type Ψ : val iProp Σ.

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

  Definition pool۰context t ctx scope : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    𝑡 γ
    base.pool۰context γ ctx scope.
  #[local] Instance : CustomIpat "context" :=
    " ( %𝑡{} & %γ{} & {%Heq{};->} & #Hmeta{_{}} & Hctx{_{}} ) ".

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

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

  Definition pool۰consumer t P : iProp Σ :=
    pool۰finished t ={}=∗
    P.

  Definition pool۰obligation t P : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    𝑡 γ
    base.pool۰obligation γ P.
  #[local] Instance : CustomIpat "obligation" :=
    " ( %𝑡{} & %γ{} & {%Heq{};->} & #Hmeta{_{}} & Hobligation{_{}} ) ".

  #[global] Instance pool۰obligationproper t :
    Proper ((≡) ==> (≡)) (pool۰obligation t).
  #[global] Instance pool۰consumerproper t :
    Proper ((≡) ==> (≡)) (pool۰consumer t).

  #[global] Instance pool۰invpersistent t sz :
    Persistent (pool۰inv t sz).
  #[global] Instance pool۰obligationpersistent t P :
    Persistent (pool۰obligation t P).
  #[global] Instance pool۰finishedpersistent t :
    Persistent (pool۰finished t).

  Lemma pool۰invagree t sz1 sz2 :
    pool۰inv t sz1 -∗
    pool۰inv t sz2 -∗
    sz1 = sz2.

  Lemma pool۰consumerintro {t} P :
    (pool۰finished t ={}=∗ P)
    pool۰consumer t P.
  Lemma pool۰consumerwand {t P1} P2 :
    pool۰consumer t P1 -∗
    (P1 -∗ P2) -∗
    pool۰consumer t P2.
  Lemma pool۰consumercombine t P1 P2 :
    pool۰consumer t P1 -∗
    pool۰consumer t P2 -∗
    pool۰consumer t (P1 P2).
  Lemma pool۰consumeror t P1 P2 :
    ( pool۰consumer t P1
     pool۰consumer t P2
    )
    pool۰consumer t (P1 P2).
  Lemma pool۰consumerexist {A} {t} (Φ : A iProp Σ) x :
    pool۰consumer t (Φ x)
    pool۰consumer t ( x, Φ x).
  Lemma pool۰consumer {A} {t} (Φ : A iProp Σ) x :
    pool۰consumer t ( x, Φ x)
    pool۰consumer t (Φ x).
  Lemma pool۰consumerfinished t P :
    pool۰consumer t P -∗
    pool۰finished t ={}=∗
    P.
  #[global] Instance pool۰consumermono t :
    Proper ((⊢) ==> (⊢)) (pool۰consumer t).
  #[global] Instance pool۰consumerflipmono t :
    Proper (flip (⊢) ==> flip (⊢)) (pool۰consumer t).

  Lemma pool۰obligationwand {t P1} P2 :
    pool۰obligation t P1 -∗
     (P1 -∗ P2) -∗
    pool۰obligation t P2.
  Lemma pool۰obligationsplit t P1 P2 :
    pool۰obligation t (P1 P2)
      pool۰obligation t P1
      pool۰obligation t P2.
  Lemma pool۰obligationcombine t P1 P2 :
    pool۰obligation t P1 -∗
    pool۰obligation t P2 -∗
    pool۰obligation t (P1 P2).
  Lemma pool۰obligationfinished t P :
    pool۰obligation t P -∗
    pool۰finished t -∗
     P.

  Lemma pool٠createspec sz :
    (0 sz)%Z
    {{{
      True
    }}}
      pool٠create #sz
    {{{
      t
    , RET t;
      pool۰inv t sz
      pool۰model t
    }}}.

  Lemma pool٠run_onspec Ψ t task :
    {{{
      pool۰model t
      ( ctx scope,
        pool۰context t ctx scope -∗
        WP task ctx {{ v,
          pool۰context t ctx scope
          Ψ v
        }}
      )
    }}}
      pool٠run_on t task
    {{{
      v
    , RET v;
      pool۰model t
      Ψ v
    }}}.

  Lemma pool٠closespec t :
    {{{
      pool۰model t
    }}}
      pool٠close t
    {{{
      RET ();
      pool۰finished t
    }}}.

  Lemma pool٠runspec (Ψ : val val iProp Σ) sz task :
    (0 sz)%Z
    {{{
       t ctx scope,
      pool۰inv t sz -∗
      pool۰context t ctx scope -∗
      WP task ctx {{ v,
        pool۰context t ctx scope
        Ψ t v
      }}
    }}}
      pool٠run #sz task
    {{{
      t v
    , RET v;
      pool۰finished t
      Ψ t v
    }}}.

  Lemma pool٠sizespec t sz ctx scope :
    {{{
      pool۰inv t sz
      pool۰context t ctx scope
    }}}
      pool٠size ctx
    {{{
      RET #sz;
      pool۰context t ctx scope
    }}}.

  Lemma pool٠asyncspec P Q t ctx scope task :
    {{{
      pool۰context t ctx scope
      ( ctx scope,
        pool۰context t ctx scope -∗
        WP task ctx {{ res,
          pool۰context t ctx scope
           P
           Q
        }}
      )
    }}}
      pool٠async ctx task
    {{{
      RET ();
      pool۰context t ctx scope
      pool۰consumer t P
      pool۰obligation t Q
    }}}.

  Lemma pool٠waitspec P_notification P_pred Q_pred t ctx scope notification pred :
    {{{
      pool۰context t ctx scope
      P_notification
      ( notify,
        P_notification -∗
        WP notify () {{ itype۰unit }} -∗
        WP notification notify {{ res,
          res = ()%V
          P_notification
        }}
      )
      P_pred
       (
        P_pred -∗
        WP pred () {{ res,
           b,
          res = #b
          if b then Q_pred else P_pred
        }}
      )
    }}}
      pool٠wait ctx notification pred
    {{{
      RET ();
      pool۰context t ctx scope
      Q_pred
    }}}.

  Lemma pool٠wait_ivarspec `{ivar۰G : !Ivar4G Σ} {context_name} t ctx scope ivar Ψ Ξ (Γ : _ context_name _) :
    {{{
      pool۰context t ctx scope
      ivar_4۰inv ivar Ψ Ξ Γ
    }}}
      pool٠wait_ivar ctx ivar
    {{{
      RET ();
      £ 2
      pool۰context t ctx scope
      ivar_4۰resolved ivar
    }}}.
End pool۰G.

#[global] Opaque pool۰scope.
#[global] Opaque pool۰inv.
#[global] Opaque pool۰model.
#[global] Opaque pool۰context.
#[global] Opaque pool۰obligation.
#[global] Opaque pool۰consumer.
#[global] Opaque pool۰finished.

Section pool۰G.
  Context `{pool۰G : PoolG Σ}.

  Implicit Type P Q R : iProp Σ.

  #[global] Instance from_assumptionpool۰consumer t p P Q :
    FromAssumption p P Q
    KnownRFromAssumption p P (pool۰consumer t Q).

  #[global] Instance from_purepool۰consumer t a P ϕ :
    FromPure a P ϕ
    FromPure a (pool۰consumer t P) ϕ.

  #[global] Instance into_wandpool۰consumer t p q R P Q :
    IntoWand false false R P Q
    IntoWand p q (pool۰consumer t R) (pool۰consumer t P) (pool۰consumer t Q).
  #[global] Instance into_wandpool۰consumerpersistent t p q R P Q :
    IntoWand false q R P Q
    IntoWand p q (pool۰consumer t R) P (pool۰consumer t Q).
  #[global] Instance into_wandpool۰consumerargs t p q R P Q :
    IntoWand p false R P Q
    IntoWand' p q R (pool۰consumer t P) (pool۰consumer t Q).

  #[global] Instance from_seppool۰consumer t P Q1 Q2 :
    FromSep P Q1 Q2
    FromSep (pool۰consumer t P) (pool۰consumer t Q1) (pool۰consumer t Q2).

  #[global] Instance from_orpool۰consumer t P Q1 Q2 :
    FromOr P Q1 Q2
    FromOr (pool۰consumer t P) (pool۰consumer t Q1) (pool۰consumer t Q2).

  #[global] Instance from_existpool۰consumer t {A} P (Φ : A iProp Σ) :
    FromExist P Φ
    FromExist (pool۰consumer t P) (λ a, pool۰consumer t (Φ a)).

  #[global] Instance into_forallpool۰consumer t {A} P (Φ : A iProp Σ) :
    IntoForall P Φ
    IntoForall (pool۰consumer t P) (λ a, pool۰consumer t (Φ a)).

  #[global] Instance from_modalpool۰consumer t P :
    FromModal True modality_id (pool۰consumer t P) (pool۰consumer t P) P.

  #[global] Instance elim_modalpool۰consumer t p P Q :
    ElimModal True p false (pool۰consumer t P) P (pool۰consumer t Q) (pool۰consumer t Q).

  #[global] Instance add_modalpool۰consumer t P Q :
    AddModal (pool۰consumer t P) P (pool۰consumer t Q).

  #[global] Instance framepool۰consumer t p R P Q :
    Frame p R P Q
    Frame p R (pool۰consumer t P) (pool۰consumer t Q)
  | 2.
End pool۰G.