Library zoo_parabs.ws_hub_std

From zoo Require Import
  prelude.
From zoo.common Require Import
  countable
  gmultiset
  list.
From zoo.iris.bi Require Import
  big_op.
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_parabs Require Export
  base
  ws_hub_std__code.
From zoo_parabs Require Import
  ws_hub_std__types
  ws_deques_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 : list val.
Implicit Types vss : list $ list val.
Implicit Types status : status.
Implicit Types empty : emptiness.

Class WsHubStdG ÎŁ `{zoo_G : !ZooG ÎŁ} :=
  { #[local] ws_hub_std_G_queues_G :: WsDequesPublicG ÎŁ
  ; #[local] ws_hub_std_G_waiters_G :: WaitersG ÎŁ
  }.

Definition ws_hub_std_ÎŁ :=
  #[ws_deques_public_ÎŁ
  ; waiters_ÎŁ
  ].
#[global] Instance subG_ws_hub_std_ÎŁ ÎŁ `{zoo_G : !ZooG ÎŁ} :
  subG ws_hub_std_ÎŁ ÎŁ →
  WsHubStdG ÎŁ.

#[local] Definition consistent vs vss :=
  vs = ⋃+ (list_to_set_disj <$> vss).

#[local] Lemma consistent_alloc sz :
  consistent ∅ (replicate sz []).
#[local] Lemma consistent_empty vs vss :
  consistent vs vss →
  vs = ∅ ↔
    âˆ€ i us,
    vss !! i = Some us →
    us = [].
#[local] Lemma consistent_push {vs vss i us} v :
  vss !! i = Some us →
  consistent vs vss →
  consistent ({[+v+]} ⊎ vs) (<[i := us ++ [v]]> vss).
#[local] Lemma consistent_remove {vs vss i us} us1 v us2 :
  vss !! i = Some us →
  us = us1 ++ v :: us2 →
  consistent vs vss →
    v ∈ vs ∧
    consistent (vs ∖ {[+v+]}) (<[i := us1 ++ us2]> vss).
#[local] Lemma consistent_pop vs vss i us v :
  vss !! i = Some (us ++ [v]) →
  consistent vs vss →
    v ∈ vs ∧
    consistent (vs ∖ {[+v+]}) (<[i := us]> vss).
#[local] Lemma consistent_steal vs vss i v us :
  vss !! i = Some (v :: us) →
  consistent vs vss →
    v ∈ vs ∧
    consistent (vs ∖ {[+v+]}) (<[i := us]> vss).

Opaque consistent.

Section ws_hub_std_G.
  Context `{ws_hub_std_G : WsHubStdG ÎŁ}.

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

  Record metadata :=
    { metadata_size : nat
    ; metadata_queues : val
    ; metadata_rounds : val
    ; metadata_waiters : val
    }.
  Implicit Types Îł : metadata.

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

  #[local] Definition inv_inner 𝑡 : iProp ÎŁ :=
    âˆƒ num_active,
    đ‘Ą.[num_active] ↩ #num_active.
  #[local] Instance : CustomIpat "inv_inner" :=
    " ( %num_active & H𝑡_num_active ) ".
  Definition ws_hub_std_inv t Îč sz : iProp ÎŁ :=
    âˆƒ 𝑡 Îł,
    âŒœt = #𝑡⌝ ∗
    meta 𝑡 nroot Îł ∗
    âŒœsz = Îł.(metadata_size)⌝ ∗
    đ‘Ą.[queues] ↩□ Îł.(metadata_queues) ∗
    đ‘Ą.[rounds] ↩□ Îł.(metadata_rounds) ∗
    đ‘Ą.[waiters] ↩□ Îł.(metadata_waiters) ∗
    ws_deques_public_inv Îł.(metadata_queues) Îč Îł.(metadata_size) ∗
    array_inv Îł.(metadata_rounds) Îł.(metadata_size) ∗
    waiters_inv Îł.(metadata_waiters) sz ∗
    inv nroot (inv_inner 𝑡).
  #[local] Instance : CustomIpat "inv" :=
    " ( %𝑡{} & %Îł{} & {%Heq{};->} & #Hmeta{} & -> & #H𝑡{}_queues & #H𝑡{}_rounds & #H𝑡{}_waiters & #Hqueues{}_inv & #Hrounds{}_inv & #Hwaiters{}_inv & #Hinv{} ) ".

  Definition ws_hub_std_model t vs : iProp ÎŁ :=
    âˆƒ 𝑡 Îł vss,
    âŒœt = #𝑡⌝ ∗
    meta 𝑡 nroot Îł ∗
    ws_deques_public_model Îł.(metadata_queues) vss ∗
    âŒœconsistent vs vss⌝.
  #[local] Instance : CustomIpat "model" :=
    " ( %𝑡_ & %Îł_ & %vss & %Heq & Hmeta_ & Hqueues_model & %Hconsistent ) ".

  Definition ws_hub_std_owner t i status empty : iProp ÎŁ :=
    âˆƒ 𝑡 Îł ws round n,
    âŒœt = #𝑡⌝ ∗
    meta 𝑡 nroot Îł ∗
    ws_deques_public_owner Îł.(metadata_queues) i status ws ∗
    âŒœempty = Empty → ws = []⌝ ∗
    array_slice Îł.(metadata_rounds) i DfracDiscarded [round] ∗
    random_round_model' round (Îł.(metadata_size) - 1) n.
  #[local] Instance : CustomIpat "owner" :=
    " ( %𝑡{;_} & %Îł{;_} & %ws{} & %round{} & %n{} & %Heq{} & Hmeta{;_} & Hqueues_owner{} & %Hempty{} & #Hrounds{} & Hround{} ) ".

  #[global] Instance ws_hub_std_model_timeless t vs :
    Timeless (ws_hub_std_model t vs).

  #[global] Instance ws_hub_std_inv_persistent t Îč sz :
    Persistent (ws_hub_std_inv t Îč sz).

  Lemma ws_hub_std_inv_agree t Îč sz1 sz2 :
    ws_hub_std_inv t Îč sz1 -∗
    ws_hub_std_inv t Îč sz2 -∗
    âŒœsz1 = sz2⌝.

  Lemma ws_hub_std_owner_exclusive t i status1 empty1 status2 empty2 :
    ws_hub_std_owner t i status1 empty1 -∗
    ws_hub_std_owner t i status2 empty2 -∗
    False.

  Lemma ws_hub_std_inv_owner t Îč sz i status empty :
    ws_hub_std_inv t Îč sz -∗
    ws_hub_std_owner t i status empty -∗
    âŒœi < sz⌝.

  Lemma ws_hub_std_model_empty t Îč sz vs :
    ws_hub_std_inv t Îč sz -∗
    ws_hub_std_model t vs -∗
    ( [∗ list] i ∈ seq 0 sz,
      âˆƒ status,
      ws_hub_std_owner t i status Empty
    ) -∗
    âŒœvs = ∅⌝.

  Lemma ws_hub_stdÙ create𑁒spec Îč sz :
    (0 ≀ sz)%Z →
    {{{
      True
    }}}
      ws_hub_stdÙ create #sz
    {{{
      t
    , RET t;
      ws_hub_std_inv t Îč ₊sz ∗
      ws_hub_std_model t ∅ ∗
      [∗ list] i ∈ seq 0 ₊sz,
        ws_hub_std_owner t i Nonblocked Empty
    }}}.

  Lemma ws_hub_stdÙ size𑁒spec t Îč sz :
    {{{
      ws_hub_std_inv t Îč sz
    }}}
      ws_hub_stdÙ size t
    {{{
      RET #sz;
      True
    }}}.

  #[local] Lemma ws_hub_stdÙ begin_inactive𑁒spec t Îč sz :
    {{{
      ws_hub_std_inv t Îč sz
    }}}
      ws_hub_stdÙ begin_inactive t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_stdÙ end_inactive𑁒spec t Îč sz :
    {{{
      ws_hub_std_inv t Îč sz
    }}}
      ws_hub_stdÙ end_inactive t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_stdÙ block_active𑁒spec t Îč sz i i_ empty :
    i = âși_ →
    {{{
      ws_hub_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Nonblocked empty
    }}}
      ws_hub_stdÙ block_active t #i
    {{{
      RET ();
      ws_hub_std_owner t i_ Blocked empty
    }}}.

  #[local] Lemma ws_hub_stdÙ unblock_active𑁒spec t Îč sz i i_ empty :
    i = âși_ →
    {{{
      ws_hub_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Blocked empty
    }}}
      ws_hub_stdÙ unblock_active t #i
    {{{
      RET ();
      ws_hub_std_owner t i_ Nonblocked empty
    }}}.

  Lemma ws_hub_stdÙ block𑁒spec t Îč sz i i_ empty :
    i = âși_ →
    {{{
      ws_hub_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Nonblocked empty
    }}}
      ws_hub_stdÙ block t #i
    {{{
      RET ();
      ws_hub_std_owner t i_ Blocked empty
    }}}.

  Lemma ws_hub_stdÙ unblock𑁒spec t Îč sz i i_ empty :
    i = âși_ →
    {{{
      ws_hub_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Blocked empty
    }}}
      ws_hub_stdÙ unblock t #i
    {{{
      RET ();
      ws_hub_std_owner t i_ Nonblocked empty
    }}}.

  Lemma ws_hub_stdÙ closed𑁒spec t Îč sz :
    {{{
      ws_hub_std_inv t Îč sz
    }}}
      ws_hub_stdÙ closed t
    {{{
      closed
    , RET #closed;
      True
    }}}.

  #[local] Lemma ws_hub_stdÙ notify𑁒spec t Îč sz :
    {{{
      ws_hub_std_inv t Îč sz
    }}}
      ws_hub_stdÙ notify t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_stdÙ notify_all𑁒spec t Îč sz :
    {{{
      ws_hub_std_inv t Îč sz
    }}}
      ws_hub_stdÙ notify_all t
    {{{
      RET ();
      True
    }}}.

  Lemma ws_hub_stdÙ push𑁒spec t Îč sz i i_ empty v :
    i = âși_ →
    <<<
      ws_hub_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Nonblocked empty
    | ∀∀ vs,
      ws_hub_std_model t vs
    >>>
      ws_hub_stdÙ push t #i v @ ↑Îč
    <<<
      ws_hub_std_model t ({[+v+]} ⊎ vs)
    | RET ();
      ws_hub_std_owner t i_ Nonblocked Nonempty
    >>>.

  Lemma ws_hub_stdÙ pop𑁒spec t Îč sz i i_ empty :
    i = âși_ →
    <<<
      ws_hub_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Nonblocked empty
    | ∀∀ vs,
      ws_hub_std_model t vs
    >>>
      ws_hub_stdÙ pop t #i @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_std_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | RET o;
      ws_hub_std_owner t i_ Nonblocked (if o then empty else Empty)
    >>>.

  #[local] Lemma ws_hub_stdÙ try_steal_once𑁒spec t Îč sz i i_ empty :
    i = âși_ →
    <<<
      ws_hub_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Blocked empty
    | ∀∀ vs,
      ws_hub_std_model t vs
    >>>
      ws_hub_stdÙ try_steal_once t #i @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_std_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | RET o;
      ws_hub_std_owner t i_ Blocked empty
    >>>.

  #[local] Lemma ws_hub_std_try_steal₀𑁒spec P Q t Îč sz i i_ empty yield max_round pred :
    i = âși_ →
    (0 ≀ max_round)%Z →
    <<<
      ws_hub_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Blocked empty ∗
      P ∗
      â–Ą (
        P -∗
        WP pred () {{ res,
          âˆƒ b,
          âŒœres = #b⌝ ∗
          if b then Q else P
        }}
      )
    | ∀∀ vs,
      ws_hub_std_model t vs
    >>>
      ws_hub_stdÙ try_steal₀ t #i #yield #max_round pred @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | Nothing
      | Anything ⇒
          ws_hub_std_model t vs
      | Something v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | RET o;
      ws_hub_std_owner t i_ Blocked empty ∗
      if o is Anything then Q else P
    >>>.

  #[local] Lemma ws_hub_stdÙ 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_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Blocked empty ∗
      P ∗
      â–Ą (
        P -∗
        WP pred () {{ res,
          âˆƒ b,
          âŒœres = #b⌝ ∗
          if b then Q else P
        }}
      )
    | ∀∀ vs,
      ws_hub_std_model t vs
    >>>
      ws_hub_stdÙ try_steal t #i #max_round_noyield #max_round_yield pred @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | Nothing
      | Anything ⇒
          ws_hub_std_model t vs
      | Something v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | RET o;
      ws_hub_std_owner t i_ Blocked empty ∗
      if o is Anything then Q else P
    >>>.

  #[local] Lemma ws_hub_stdÙ 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_std_inv t Îč sz ∗
      ws_hub_std_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_std_model t vs
    >>>
      ws_hub_stdÙ steal_aux t #i #max_round_noyield #max_round_yield notification pred @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_std_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | RET o;
      ws_hub_std_owner t i_ (if o then Nonblocked else Blocked) empty ∗
      P_notification ∗
      if o then P_pred else Q_pred
    >>>.

  Lemma ws_hub_stdÙ 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_std_inv t Îč sz ∗
      ws_hub_std_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_std_model t vs
    >>>
      ws_hub_stdÙ steal_until t #i #max_round_noyield #max_round_yield notification pred @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_std_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | RET o;
      ws_hub_std_owner t i_ Nonblocked empty ∗
      P_notification ∗
      if o then P_pred else Q_pred
    >>>.

  Lemma ws_hub_stdÙ 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_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Nonblocked empty
    | ∀∀ vs,
      ws_hub_std_model t vs
    >>>
      ws_hub_stdÙ steal t #i #max_round_noyield #max_round_yield @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_std_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | RET o;
      ws_hub_std_owner t i_ (if o then Nonblocked else Blocked) empty
    >>>.

  Lemma ws_hub_stdÙ close𑁒spec t Îč sz :
    {{{
      ws_hub_std_inv t Îč sz
    }}}
      ws_hub_stdÙ close t
    {{{
      RET ();
      True
    }}}.
End ws_hub_std_G.

#[global] Opaque ws_hub_std_inv.
#[global] Opaque ws_hub_std_model.
#[global] Opaque ws_hub_std_owner.

Section ws_hub_std_G.
  Context `{ws_hub_std_G : WsHubStdG ÎŁ}.

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

  Lemma ws_hub_stdÙ 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_std_inv t Îč sz ∗
      ws_hub_std_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_std_model t vs
    >>>
      ws_hub_stdÙ pop_steal_until t #i #max_round_noyield #max_round_yield notification pred @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_std_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | empty,
      RET o;
      ws_hub_std_owner t i_ Nonblocked empty ∗
      P_notification ∗
      if o then P_pred else Q_pred
    >>>.

  Lemma ws_hub_stdÙ 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_std_inv t Îč sz ∗
      ws_hub_std_owner t i_ Nonblocked empty
    | ∀∀ vs,
      ws_hub_std_model t vs
    >>>
      ws_hub_stdÙ pop_steal t #i #max_round_noyield #max_round_yield @ ↑Îč
    <<<
      âˆƒâˆƒ o,
      match o with
      | None ⇒
          ws_hub_std_model t vs
      | Some v ⇒
          âˆƒ vs',
          âŒœvs = {[+v+]} ⊎ vs'⌝ ∗
          ws_hub_std_model t vs'
      end
    | empty,
      RET o;
      ws_hub_std_owner t i_ (if o then Nonblocked else Blocked) empty ∗
      if o then
        True
      else
        âŒœempty = Empty⌝
    >>>.
End ws_hub_std_G.

From zoo_parabs Require
  ws_hub_std__opaque.