Library zoo_std.waiter_spsc

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.iris.base_logic.lib.oneshot.
Require Import zoo.iris.base_logic.lib.excl.
Require Import zoo.base.
Require Export zoo_std.waiter_spsc__code.
Require Import zoo_std.waiter_spsc__types.
Require Import zoo.options.

Implicit Type b : bool.
Implicit Type 𝑡 : location.

Class WaiterSpscG Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] waiter_spsc۰G۰mutex۰G :: MutexG Σ
  ; #[local] waiter_spsc۰G۰lstate۰G :: OneshotG Σ unit unit
  ; #[local] waiter_spsc۰G۰excl۰G :: ExclG Σ unitO
  }.

Definition waiter_spsc۰Σ :=
  #[mutex۰Σ
  ; oneshot۰Σ unit unit
  ; excl۰Σ unitO
  ].
#[global] Instance subGwaiter_spsc۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG waiter_spsc۰Σ Σ
  WaiterSpscG Σ .

Section waiter_spsc۰G.
  Context `{waiter_spsc۰G : WaiterSpscG Σ}.

  Record metadata :=
    { metadata۰mutex : val
    ; metadata۰condition : val
    ; metadata۰lstate : gname
    ; metadata۰consumer : gname
    }.
  Implicit Type γ : metadata.

  #[local] Instance metadataeq_dec : EqDecision metadata :=
    ltac:(solve_decision).
  #[local] Instance metadatacountable :
    Countable metadata.

  #[local] Definition inv۰inner 𝑡 γ P : iProp Σ :=
     b,
    𝑡.[flag] #b
    if b then
      oneshot۰shot γ.(metadata۰lstate) ()
      (P excl γ.(metadata۰consumer) ())
    else
      oneshot۰pending γ.(metadata۰lstate) (DfracOwn (1/3)) ().
  Definition waiter_spsc۰inv t P : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    𝑡 γ
    𝑡.[mutex] γ.(metadata۰mutex)
    mutex۰inv γ.(metadata۰mutex) True
    𝑡.[condition] γ.(metadata۰condition)
    condition۰inv γ.(metadata۰condition)
    inv nroot (inv۰inner 𝑡 γ P).

  Definition waiter_spsc۰producer t : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    𝑡 γ
    oneshot۰pending γ.(metadata۰lstate) (DfracOwn (2/3)) ().

  Definition waiter_spsc۰consumer t : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    𝑡 γ
    excl γ.(metadata۰consumer) ().

  Definition waiter_spsc۰notified t : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    𝑡 γ
    oneshot۰shot γ.(metadata۰lstate) ().

  #[global] Instance waiter_spsc۰invcontractive t :
    Contractive (waiter_spsc۰inv t).
  #[global] Instance waiter_spsc۰invne t :
    NonExpansive (waiter_spsc۰inv t).
  #[global] Instance waiter_spsc۰invproper t :
    Proper ((≡) ==> (≡)) (waiter_spsc۰inv t).

  #[global] Instance waiter_spsc۰producertimeless t :
    Timeless (waiter_spsc۰producer t).
  #[global] Instance waiter_spsc۰consumertimeless t :
    Timeless (waiter_spsc۰consumer t).
  #[global] Instance waiter_spsc۰notifiedtimeless t :
    Timeless (waiter_spsc۰notified t).

  #[global] Instance waiter_spsc۰invpersistent t P :
    Persistent (waiter_spsc۰inv t P).
  #[global] Instance waiter_spsc۰notifiedpersistent t :
    Persistent (waiter_spsc۰notified t).

  Lemma waiter_spsc۰producerexclusive t :
    waiter_spsc۰producer t -∗
    waiter_spsc۰producer t -∗
    False.

  Lemma waiter_spsc۰consumerexclusive t :
    waiter_spsc۰consumer t -∗
    waiter_spsc۰consumer t -∗
    False.

  Lemma waiter_spsc٠createspec P :
    {{{
      True
    }}}
      waiter_spsc٠create ()
    {{{
      t
    , RET t;
      waiter_spsc۰inv t P
      waiter_spsc۰producer t
      waiter_spsc۰consumer t
    }}}.

  Lemma waiter_spsc٠notifyspec t P :
    {{{
      waiter_spsc۰inv t P
      waiter_spsc۰producer t
      P
    }}}
      waiter_spsc٠notify t
    {{{
      RET ();
      waiter_spsc۰notified t
    }}}.

  Lemma waiter_spsc٠try_waitspec t P :
    {{{
      waiter_spsc۰inv t P
      waiter_spsc۰consumer t
    }}}
      waiter_spsc٠try_wait t
    {{{
      b
    , RET #b;
      if b then
        P
      else
        waiter_spsc۰consumer t
    }}}.
  Lemma waiter_spsc٠try_waitspecnotified t P :
    {{{
      waiter_spsc۰inv t P
      waiter_spsc۰consumer t
      waiter_spsc۰notified t
    }}}
      waiter_spsc٠try_wait t
    {{{
      RET true;
      P
    }}}.

  Lemma waiter_spsc٠waitspec t P :
    {{{
      waiter_spsc۰inv t P
      waiter_spsc۰consumer t
    }}}
      waiter_spsc٠wait t
    {{{
      RET ();
      P
    }}}.
End waiter_spsc۰G.

Require zoo_std.waiter_spsc__opaque.

#[global] Opaque waiter_spsc۰inv.
#[global] Opaque waiter_spsc۰producer.
#[global] Opaque waiter_spsc۰consumer.
#[global] Opaque waiter_spsc۰notified.