Library zoo_parabs.ws_hub_std

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.common.gmultiset.
Require Import zoo.common.list.
Require Import zoo.iris.bi.big_op.
Require Import zoo.base.
Require Import zoo_std.option.
Require Export zoo_parabs.base.
Require Export zoo_parabs.ws_hub_std__code.
Require Import zoo_parabs.ws_hub_std__types.
Require Import zoo.options.

Implicit Type b yield closed : bool.
Implicit Type num_active : Z.
Implicit Type 𝑡 : location.
Implicit Type v t notification notify pred : val.
Implicit Type vs : gmultiset val.
Implicit Type ws us : list val.
Implicit Type vss : list $ list val.
Implicit Type status : status.
Implicit Type empty : emptiness.

Class WsHubStdG Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] ws_hub_std۰G۰deques۰G :: WsDequesPublicG Σ
  ; #[local] ws_hub_std۰G۰waiters۰G :: WaitersG Σ
  }.

Definition ws_hub_std۰Σ :=
  #[ws_deques_public۰Σ
  ; waiters۰Σ
  ].
#[global] Instance subGws_hub_std۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG ws_hub_std۰Σ Σ
  WsHubStdG Σ.

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

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

  #[local] Lemma consistentempty vs vss :
    consistent vs vss
    vs =
       i us,
      vss !! i = Some us
      us = [].

  #[local] Lemma consistentpush {vs vss i us} v :
    vss !! i = Some us
    consistent vs vss
    consistent ({[+v+]} vs) (<[i := us ++ [v]]> vss).
  #[local] Lemma consistentremove {vs vss i us} us1 v us2 :
    vss !! i = Some us
    us = us1 ++ v :: us2
    consistent vs vss
       vs',
      vs = {[+v+]} vs'
      consistent vs' (<[i := us1 ++ us2]> vss).
  #[local] Lemma consistentpop vs vss i us v :
    vss !! i = Some (us ++ [v])
    consistent vs vss
       vs',
      vs = {[+v+]} vs'
      consistent vs' (<[i := us]> vss).
  #[local] Lemma consistentsteal vs vss i v us :
    vss !! i = Some (v :: us)
    consistent vs vss
       vs',
      vs = {[+v+]} vs'
      consistent vs' (<[i := us]> vss).
End consistent.

Opaque consistent.

Section ws_hub_std۰G.
  Context `{ws_hub_std۰G : WsHubStdG Σ}.

  Implicit Type P P_notification P_pred Q Q_pred : iProp Σ.

  Record metadata :=
    { metadata۰size : nat
    ; metadata۰deques : val
    ; metadata۰rounds : val
    ; metadata۰waiters : val
    }.
  Implicit Type γ : metadata.

  #[local] Instance metadataeq_dec :
    EqDecision metadata.
  #[local] Instance metadatacountable :
    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 = #𝑡
    𝑡 γ
    sz = γ.(metadata۰size)
    𝑡.[deques] γ.(metadata۰deques)
    𝑡.[rounds] γ.(metadata۰rounds)
    𝑡.[waiters] γ.(metadata۰waiters)
    ws_deques_public۰inv γ.(metadata۰deques) ι γ.(metadata۰size)
    array۰inv γ.(metadata۰rounds) γ.(metadata۰size)
    waiters۰inv γ.(metadata۰waiters) sz
    inv nroot (inv۰inner 𝑡).
  #[local] Instance : CustomIpat "inv" :=
    " ( %𝑡{} & %γ{} & {%Heq{};->} & #Hmeta{} & -> & #H𝑡{}_deques & #H𝑡{}_rounds & #H𝑡{}_waiters & #Hdeques{}_inv & #Hrounds{}_inv & #Hwaiters{}_inv & #Hinv{} ) ".

  Definition ws_hub_std۰model t vs : iProp Σ :=
     𝑡 γ vss,
    t = #𝑡
    𝑡 γ
    ws_deques_public۰model γ.(metadata۰deques) vss
    consistent vs vss.
  #[local] Instance : CustomIpat "model" :=
    " ( %𝑡_ & %γ_ & %vss & %Heq & Hmeta_ & Hdeques_model & %Hconsistent ) ".

  Definition ws_hub_std۰owner t i status empty : iProp Σ :=
     𝑡 γ ws round n,
    t = #𝑡
    𝑡 γ
    ws_deques_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.
  #[local] Instance : CustomIpat "owner" :=
    " ( %𝑡{;_} & %γ{;_} & %ws{} & %round{} & %n{} & %Heq{} & Hmeta{;_} & Hdeques_owner{} & %Hempty{} & #Hrounds{} & Hround{} ) ".

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

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

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

  Lemma ws_hub_std۰ownerexclusive 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_stdinvowner 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۰modelempty 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٠createspec ι 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٠sizespec t ι sz :
    {{{
      ws_hub_std۰inv t ι sz
    }}}
      ws_hub_std٠size t
    {{{
      RET #sz;
      True
    }}}.

  #[local] Lemma ws_hub_std٠begin_inactivespec t ι sz :
    {{{
      ws_hub_std۰inv t ι sz
    }}}
      ws_hub_std٠begin_inactive t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_std٠end_inactivespec t ι sz :
    {{{
      ws_hub_std۰inv t ι sz
    }}}
      ws_hub_std٠end_inactive t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_std٠block_activespec 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_activespec 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٠blockspec 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٠unblockspec 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٠closedspec t ι sz :
    {{{
      ws_hub_std۰inv t ι sz
    }}}
      ws_hub_std٠closed t
    {{{
      closed
    , RET #closed;
      True
    }}}.

  #[local] Lemma ws_hub_std٠notifyspec t ι sz :
    {{{
      ws_hub_std۰inv t ι sz
    }}}
      ws_hub_std٠notify t
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma ws_hub_std٠notify_allspec t ι sz :
    {{{
      ws_hub_std۰inv t ι sz
    }}}
      ws_hub_std٠notify_all t
    {{{
      RET ();
      True
    }}}.

  Lemma ws_hub_std٠pushspec 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٠popspec 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_oncespec 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_stealspec 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_auxspec 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_untilspec 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٠stealspec 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٠closespec 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 Type P P_notification P_pred Q Q_pred : iProp Σ.

  Lemma ws_hub_std٠pop_steal_untilspec 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_stealspec 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.

Require zoo_parabs.ws_hub_std__opaque.