Library zoo_parabs.ws_hub_hybrid

From zoo Require Import
  prelude.
From zoo.common Require Import
  countable
  gmultiset
  list.
From zoo.iris.bi Require Import
  big_op.
From zoo.iris.base_logic Require Import
  lib.ghost_list.
From zoo.language Require Import
  notations.
From zoo.diaframe Require Import
  diaframe.
From zoo_std Require Import
  int
  option
  optional
  array
  random_round
  domain.
From zoo_saturn Require Import
  mpmc_queue_1.
From zoo_parabs Require Export
  base
  ws_hub_hybrid__code.
From zoo_parabs Require Import
  ws_hub_hybrid__types
  ws_bdeques_public
  waiters.
From zoo Require Import
  options.

Implicit Types b yield closed : bool.
Implicit Types num_active : Z.
Implicit Types ð‘Ą : location.
Implicit Types v t notification notify pred : val.
Implicit Types vs : gmultiset val.
Implicit Types ws us vs_queue : list val.
Implicit Types vss : list $ list val.
Implicit Types status : status.
Implicit Types empty : emptiness.

Class WsHubHybridG ÎĢ `{zoo_G : !ZooG ÎĢ} :=
  { #[local] ws_hub_hybrid_G_deques_G :: WsBdequesPublicG ÎĢ
  ; #[local] ws_hub_hybrid_G_queue_G :: MpmcQueue1G ÎĢ
  ; #[local] ws_hub_hybrid_G_waiters_G :: WaitersG ÎĢ
  ; #[local] ws_hub_hybrid_G_emptiness_G :: GhostListG ÎĢ emptiness
  }.

Definition ws_hub_hybrid_ÎĢ :=
  #[ws_bdeques_public_ÎĢ
  ; mpmc_queue_1_ÎĢ
  ; waiters_ÎĢ
  ; ghost_list_ÎĢ emptiness
  ].
#[global] Instance subG_ws_hub_hybrid_ÎĢ ÎĢ `{zoo_G : !ZooG ÎĢ} :
  subG ws_hub_hybrid_ÎĢ ÎĢ â†’
  WsHubHybridG ÎĢ.

Section consistent.
  #[local] Definition consistent vs vss vs_queue :=
    vs =
      â‹ƒ+ (list_to_set_disj <$> vss) ⊎
      list_to_set_disj vs_queue.

  #[local] Lemma consistent_alloc sz :
    consistent ∅ (replicate sz []) [].

  #[local] Lemma consistent_empty vs vss vs_queue :
    consistent vs vss vs_queue →
    vs = ∅ ↔
      ( ∀ i us,
        vss !! i = Some us →
        us = []
      ) ∧
      vs_queue = [].

  #[local] Lemma consistent_deque_push {vs vss vs_queue i us} v :
    vss !! i = Some us →
    consistent vs vss vs_queue →
    consistent ({[+v+]} ⊎ vs) (<[i := us ++ [v]]> vss) vs_queue.
  #[local] Lemma consistent_deque_remove {vs vss vs_queue i us} us1 v us2 :
    vss !! i = Some us →
    us = us1 ++ v :: us2 →
    consistent vs vss vs_queue →
      âˆƒ vs',
      vs = {[+v+]} ⊎ vs' ∧
      consistent vs' (<[i := us1 ++ us2]> vss) vs_queue.
  #[local] Lemma consistent_deque_pop vs vss vs_queue i us v :
    vss !! i = Some (us ++ [v]) →
    consistent vs vss vs_queue →
      âˆƒ vs',
      vs = {[+v+]} ⊎ vs' ∧
      consistent vs' (<[i := us]> vss) vs_queue.
  #[local] Lemma consistent_deque_steal vs vss vs_queue i v us :
    vss !! i = Some (v :: us) →
    consistent vs vss vs_queue →
      âˆƒ vs',
      vs = {[+v+]} ⊎ vs' ∧
      consistent vs' (<[i := us]> vss) vs_queue.

  #[local] Lemma consistent_queue_push {vs vss vs_queue} v :
    consistent vs vss vs_queue →
    consistent ({[+v+]} ⊎ vs) vss (vs_queue ++ [v]).
  #[local] Lemma consistent_queue_pop vs vss v vs_queue :
    consistent vs vss (v :: vs_queue) →
      âˆƒ vs',
      vs = {[+v+]} ⊎ vs' ∧
      consistent vs' vss vs_queue.
End consistent.

Opaque consistent.

Section ws_hub_hybrid_G.
  Context `{ws_hub_hybrid_G : WsHubHybridG ÎĢ}.

  Implicit Types P P_notification P_pred Q Q_pred : iProp ÎĢ.

  Record metadata :=
    { metadata_size : nat
    ; metadata_deques : val
    ; metadata_rounds : val
    ; metadata_queue : val
    ; metadata_waiters : val
    ; metadata_emptiness : gname
    }.
  Implicit Types Îģ : metadata.

  #[local] Instance metadata_eq_dec :
    EqDecision metadata.
  #[local] Instance metadata_countable :
    Countable metadata.

  #[local] Definition emptiness_auth' Îģ_emptiness sz vs_queue : iProp ÎĢ :=
    âˆƒ emptys,
    ghost_list_auth Îģ_emptiness emptys ∗
    âŒœlength emptys = sz⌝ ∗
    âŒœ vs_queue = []
    âˆĻ ∃ i,
      emptys !! i = Some Nonempty
    âŒ.
  #[local] Definition emptiness_auth Îģ :=
    emptiness_auth' Îģ.(metadata_emptiness) Îģ.(metadata_size).
  #[local] Instance : CustomIpat "emptiness_auth" :=
    " ( %emptys & Hauth & %Hemptys & %Hemptiness ) ".
  #[local] Definition emptiness_at' Îģ_emptiness i :=
    ghost_list_at Îģ_emptiness i (DfracOwn 1).
  #[local] Definition emptiness_at Îģ :=
    emptiness_at' Îģ.(metadata_emptiness).

  #[local] Definition inv_inner ð‘Ą : iProp ÎĢ :=
    âˆƒ num_active,
    ð‘Ą.[num_active] â†Ķ #num_active.
  #[local] Instance : CustomIpat "inv_inner" :=
    " ( %num_active & Hð‘Ą_num_active ) ".
  Definition ws_hub_hybrid_inv t Îđ sz : iProp ÎĢ :=
    âˆƒ ð‘Ą Îģ,
    âŒœt = #ð‘ĄâŒ ∗
    ð‘Ą ↩ Îģ ∗
    âŒœsz = Îģ.(metadata_size)⌝ ∗
    ð‘Ą.[deques] â†Ķ□ Îģ.(metadata_deques) ∗
    ð‘Ą.[rounds] â†Ķ□ Îģ.(metadata_rounds) ∗
    ð‘Ą.[queue] â†Ķ□ Îģ.(metadata_queue) ∗
    ð‘Ą.[waiters] â†Ķ□ Îģ.(metadata_waiters) ∗
    ws_bdeques_public_inv Îģ.(metadata_deques) Îđ Îģ.(metadata_size) ∗
    array_inv Îģ.(metadata_rounds) Îģ.(metadata_size) ∗
    mpmc_queue_1_inv Îģ.(metadata_queue) Îđ ∗
    waiters_inv Îģ.(metadata_waiters) sz ∗
    inv nroot (inv_inner ð‘Ą).
  #[local] Instance : CustomIpat "inv" :=
    " ( %ð‘Ą{} & %Îģ{} & {%Heq{};->} & #Hmeta{} & -> & #Hð‘Ą{}_deques & #Hð‘Ą{}_queue & #Hð‘Ą{}_rounds & #Hð‘Ą{}_waiters & #Hdeques{}_inv & #Hrounds{}_inv & #Hqueue{}_inv & #Hwaiters{}_inv & #Hinv{} ) ".

  Definition ws_hub_hybrid_model t vs : iProp ÎĢ :=
    âˆƒ ð‘Ą Îģ vss vs_queue,
    âŒœt = #ð‘ĄâŒ ∗
    ð‘Ą ↩ Îģ ∗
    ws_bdeques_public_model Îģ.(metadata_deques) vss ∗
    mpmc_queue_1_model Îģ.(metadata_queue) vs_queue ∗
    âŒœconsistent vs vss vs_queue⌝ ∗
    emptiness_auth Îģ vs_queue.
  #[local] Instance : CustomIpat "model" :=
    " ( %ð‘Ą_ & %Îģ_ & %vss & %vs_queue & %Heq & Hmeta_ & Hdeques_model & Hqueue_model & %Hconsistent & Hemptiness_auth ) ".

  Definition ws_hub_hybrid_owner t i status empty : iProp ÎĢ :=
    âˆƒ ð‘Ą Îģ ws round n,
    âŒœt = #ð‘ĄâŒ ∗
    ð‘Ą ↩ Îģ ∗
    ws_bdeques_public_owner Îģ.(metadata_deques) i status ws ∗
    âŒœempty = Empty → ws = []⌝ ∗
    array_slice Îģ.(metadata_rounds) i DfracDiscarded [round] ∗
    random_round_model' round (Îģ.(metadata_size) - 1) n ∗
    emptiness_at Îģ i empty.
  #[local] Instance : CustomIpat "owner" :=
    " ( %ð‘Ą{;_} & %Îģ{;_} & %ws{} & %round{} & %n{} & %Heq{} & Hmeta{;_} & Hdeques_owner{} & %Hempty{} & #Hrounds{} & Hround{} & Hemptiness_at{_{}} ) ".

  #[global] Instance ws_hub_hybrid_model_timeless t vs :
    Timeless (ws_hub_hybrid_model t vs).

  #[global] Instance ws_hub_hybrid_inv_persistent t Îđ sz :
    Persistent (ws_hub_hybrid_inv t Îđ sz).

  #[local] Lemma emptiness_alloc sz :
    âŠĒ |==>
      âˆƒ Îģ_emptiness,
      emptiness_auth' Îģ_emptiness sz [] ∗
      [∗ list] i ∈ seq 0 sz,
        emptiness_at' Îģ_emptiness i Empty.
  #[local] Lemma emptiness_at_valid Îģ vs_queue i empty :
    emptiness_auth Îģ vs_queue -∗
    emptiness_at Îģ i empty -∗
    âŒœi < Îģ.(metadata_size)⌝.
  #[local] Lemma emptiness_empty Îģ vs_queue :
    emptiness_auth Îģ vs_queue -∗
    ( [∗ list] i ∈ seq 0 Îģ.(metadata_size),
      emptiness_at Îģ i Empty
    ) -∗
    âŒœvs_queue = []⌝.
  #[local] Lemma emptiness_update_auth Îģ v vs_queue :
    emptiness_auth Îģ (v :: vs_queue) âŠĒ
    emptiness_auth Îģ vs_queue.
  #[local] Lemma emptiness_update_Nonempty {Îģ vs_queue i empty} vs_queue' :
    emptiness_auth Îģ vs_queue -∗
    emptiness_at Îģ i empty ==∗
      emptiness_auth Îģ vs_queue' ∗
      emptiness_at Îģ i Nonempty.
  #[local] Lemma emptiness_update_Empty Îģ i empty :
    emptiness_auth Îģ [] -∗
    emptiness_at Îģ i empty ==∗
      emptiness_auth Îģ [] ∗
      emptiness_at Îģ i Empty.

  Opaque emptiness_auth'.

  Lemma ws_hub_hybrid_inv_agree t Îđ sz1 sz2 :
    ws_hub_hybrid_inv t Îđ sz1 -∗
    ws_hub_hybrid_inv t Îđ sz2 -∗
    âŒœsz1 = sz2⌝.

  Lemma ws_hub_hybrid_owner_exclusive t i status1 empty1 status2 empty2 :
    ws_hub_hybrid_owner t i status1 empty1 -∗
    ws_hub_hybrid_owner t i status2 empty2 -∗
    False.

  Lemma ws_hub_hybrid_inv_owner t Îđ sz i status empty :
    ws_hub_hybrid_inv t Îđ sz -∗
    ws_hub_hybrid_owner t i status empty -∗
    âŒœi < sz⌝.

  Lemma ws_hub_hybrid_model_empty t Îđ sz vs :
    ws_hub_hybrid_inv t Îđ sz -∗
    ws_hub_hybrid_model t vs -∗
    ( [∗ list] i ∈ seq 0 sz,
      âˆƒ status,
      ws_hub_hybrid_owner t i status Empty
    ) -∗
    âŒœvs = ∅⌝.

  Lemma ws_hub_hybridŲ create𑁒spec Îđ sz :
    (0 â‰Ī sz)%Z →
    {{{
      True
    }}}
      ws_hub_hybridŲ create #sz
    {{{
      t
    , RET t;
      ws_hub_hybrid_inv t Îđ ₊sz ∗
      ws_hub_hybrid_model t ∅ ∗
      [∗ list] i ∈ seq 0 ₊sz,
        ws_hub_hybrid_owner t i Nonblocked Empty
    }}}.

  Lemma ws_hub_hybridŲ size𑁒spec t Îđ sz :
    {{{
      ws_hub_hybrid_inv t Îđ sz
    }}}
      ws_hub_hybridŲ size t
    {{{
      RET #sz;
      True
    }}}.

  #[local] Lemma ws_hub_hybridŲ begin_inactive𑁒spec t Îđ sz :
    {{{
      ws_hub_hybrid_inv t Îđ sz
    }}}
      ws_hub_hybridŲ begin_inactive t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_hybridŲ end_inactive𑁒spec t Îđ sz :
    {{{
      ws_hub_hybrid_inv t Îđ sz
    }}}
      ws_hub_hybridŲ end_inactive t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_hybridŲ block_active𑁒spec t Îđ sz i i_ empty :
    i = ⁚i_ →
    {{{
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Nonblocked empty
    }}}
      ws_hub_hybridŲ block_active t #i
    {{{
      RET ();
      ws_hub_hybrid_owner t i_ Blocked empty
    }}}.

  #[local] Lemma ws_hub_hybridŲ unblock_active𑁒spec t Îđ sz i i_ empty :
    i = ⁚i_ →
    {{{
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Blocked empty
    }}}
      ws_hub_hybridŲ unblock_active t #i
    {{{
      RET ();
      ws_hub_hybrid_owner t i_ Nonblocked empty
    }}}.

  Lemma ws_hub_hybridŲ block𑁒spec t Îđ sz i i_ empty :
    i = ⁚i_ →
    {{{
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Nonblocked empty
    }}}
      ws_hub_hybridŲ block t #i
    {{{
      RET ();
      ws_hub_hybrid_owner t i_ Blocked empty
    }}}.

  Lemma ws_hub_hybridŲ unblock𑁒spec t Îđ sz i i_ empty :
    i = ⁚i_ →
    {{{
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Blocked empty
    }}}
      ws_hub_hybridŲ unblock t #i
    {{{
      RET ();
      ws_hub_hybrid_owner t i_ Nonblocked empty
    }}}.

  Lemma ws_hub_hybridŲ closed𑁒spec t Îđ sz :
    {{{
      ws_hub_hybrid_inv t Îđ sz
    }}}
      ws_hub_hybridŲ closed t
    {{{
      closed
    , RET #closed;
      True
    }}}.

  #[local] Lemma ws_hub_hybridŲ notify𑁒spec t Îđ sz :
    {{{
      ws_hub_hybrid_inv t Îđ sz
    }}}
      ws_hub_hybridŲ notify t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_hybridŲ notify_all𑁒spec t Îđ sz :
    {{{
      ws_hub_hybrid_inv t Îđ sz
    }}}
      ws_hub_hybridŲ notify_all t
    {{{
      RET ();
      True
    }}}.

  Lemma ws_hub_hybridŲ push𑁒spec t Îđ sz i i_ empty v :
    i = ⁚i_ →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Nonblocked empty
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ push t #i v @ ↑Îđ
    <<<
      ws_hub_hybrid_model t ({[+v+]} ⊎ vs)
    | RET ();
      ws_hub_hybrid_owner t i_ Nonblocked Nonempty
    >>>.

  Lemma ws_hub_hybridŲ pop𑁒spec t Îđ sz i i_ empty :
    i = ⁚i_ →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Nonblocked empty
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ pop t #i @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_hybrid_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | RET o;
      ws_hub_hybrid_owner t i_ Nonblocked (if o then empty else Empty)
    >>>.

  #[local] Lemma ws_hub_hybridŲ try_steal_once𑁒spec t Îđ sz i i_ empty :
    i = ⁚i_ →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Blocked empty
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ try_steal_once t #i @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_hybrid_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | RET o;
      ws_hub_hybrid_owner t i_ Blocked empty
    >>>.

  #[local] Lemma ws_hub_hybrid_try_steal₀𑁒spec P Q t Îđ sz i i_ empty yield max_round pred :
    i = ⁚i_ →
    (0 â‰Ī max_round)%Z →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Blocked empty ∗
      P ∗
      â–Ą (
        P -∗
        WP pred () {{ res,
          âˆƒ b,
          âŒœres = #b⌝ ∗
          if b then Q else P
        }}
      )
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ try_steal₀ t #i #yield #max_round pred @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | Nothing
      | Anything ⇒
          ws_hub_hybrid_model t vs
      | Something v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | RET o;
      ws_hub_hybrid_owner t i_ Blocked empty ∗
      if o is Anything then Q else P
    >>>.

  #[local] Lemma ws_hub_hybridŲ try_steal𑁒spec P Q t Îđ sz i i_ empty max_round_noyield max_round_yield pred :
    i = ⁚i_ →
    (0 â‰Ī max_round_noyield)%Z →
    (0 â‰Ī max_round_yield)%Z →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Blocked empty ∗
      P ∗
      â–Ą (
        P -∗
        WP pred () {{ res,
          âˆƒ b,
          âŒœres = #b⌝ ∗
          if b then Q else P
        }}
      )
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ try_steal t #i #max_round_noyield #max_round_yield pred @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | Nothing
      | Anything ⇒
          ws_hub_hybrid_model t vs
      | Something v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | RET o;
      ws_hub_hybrid_owner t i_ Blocked empty ∗
      if o is Anything then Q else P
    >>>.

  #[local] Lemma ws_hub_hybridŲ steal_aux𑁒spec P_notification P_pred Q_pred t Îđ sz i i_ empty max_round_noyield max_round_yield notification pred :
    i = ⁚i_ →
    (0 â‰Ī max_round_noyield)%Z →
    (0 â‰Ī max_round_yield)%Z →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Blocked empty ∗
      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
        }}
      )
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ steal_aux t #i #max_round_noyield #max_round_yield notification pred @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_hybrid_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | RET o;
      ws_hub_hybrid_owner t i_ (if o then Nonblocked else Blocked) empty ∗
      P_notification ∗
      if o then P_pred else Q_pred
    >>>.

  Lemma ws_hub_hybridŲ steal_until𑁒spec P_notification P_pred Q_pred t Îđ sz i i_ empty max_round_noyield max_round_yield notification pred :
    i = ⁚i_ →
    (0 â‰Ī max_round_noyield)%Z →
    (0 â‰Ī max_round_yield)%Z →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Nonblocked empty ∗
      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
        }}
      )
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ steal_until t #i #max_round_noyield #max_round_yield notification pred @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_hybrid_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | RET o;
      ws_hub_hybrid_owner t i_ Nonblocked empty ∗
      P_notification ∗
      if o then P_pred else Q_pred
    >>>.

  Lemma ws_hub_hybridŲ steal𑁒spec t Îđ sz i i_ empty max_round_noyield max_round_yield :
    i = ⁚i_ →
    (0 â‰Ī max_round_noyield)%Z →
    (0 â‰Ī max_round_yield)%Z →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Nonblocked empty
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ steal t #i #max_round_noyield #max_round_yield @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_hybrid_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | RET o;
      ws_hub_hybrid_owner t i_ (if o then Nonblocked else Blocked) empty
    >>>.

  Lemma ws_hub_hybridŲ close𑁒spec t Îđ sz :
    {{{
      ws_hub_hybrid_inv t Îđ sz
    }}}
      ws_hub_hybridŲ close t
    {{{
      RET ();
      True
    }}}.
End ws_hub_hybrid_G.

#[global] Opaque ws_hub_hybrid_inv.
#[global] Opaque ws_hub_hybrid_model.
#[global] Opaque ws_hub_hybrid_owner.

Section ws_hub_hybrid_G.
  Context `{ws_hub_hybrid_G : WsHubHybridG ÎĢ}.

  Implicit Types P P_notification P_pred Q Q_pred : iProp ÎĢ.

  Lemma ws_hub_hybridŲ pop_steal_until𑁒spec P_notification P_pred Q_pred t Îđ sz i i_ empty max_round_noyield max_round_yield notification pred :
    i = ⁚i_ →
    (0 â‰Ī max_round_noyield)%Z →
    (0 â‰Ī max_round_yield)%Z →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Nonblocked empty ∗
      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
        }}
      )
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ pop_steal_until t #i #max_round_noyield #max_round_yield notification pred @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_hybrid_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | empty,
      RET o;
      ws_hub_hybrid_owner t i_ Nonblocked empty ∗
      P_notification ∗
      if o then P_pred else Q_pred
    >>>.

  Lemma ws_hub_hybridŲ pop_steal𑁒spec t Îđ sz i i_ empty max_round_noyield max_round_yield :
    i = ⁚i_ →
    (0 â‰Ī max_round_noyield)%Z →
    (0 â‰Ī max_round_yield)%Z →
    <<<
      ws_hub_hybrid_inv t Îđ sz ∗
      ws_hub_hybrid_owner t i_ Nonblocked empty
    | ∀∀ vs,
      ws_hub_hybrid_model t vs
    >>>
      ws_hub_hybridŲ pop_steal t #i #max_round_noyield #max_round_yield @ ↑Îđ
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_hybrid_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_hybrid_model t vs'
      end
    | empty,
      RET o;
      ws_hub_hybrid_owner t i_ (if o then Nonblocked else Blocked) empty ∗
      if o then
        True
      else
        âŒœempty = Empty⌝
    >>>.
End ws_hub_hybrid_G.

From zoo_parabs Require
  ws_hub_hybrid__opaque.