Library zoo_std.semaphore

Require Import stdpp.finite.

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.iris.bi.big_op.
Require Import zoo.iris.base_logic.lib.excl.
Require Import zoo.base.
Require Export zoo_std.semaphore__code.
Require Import zoo_std.semaphore__types.
Require Import zoo.options.

Implicit Type b : bool.
Implicit Type cnt : nat.
Implicit Type l : location.
Implicit Type t : val.

Class SemaphoreG Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] semaphore۰G۰mutex۰G :: MutexG Σ
  ; #[local] semaphore۰G۰tokens۰G :: ExclG Σ unitO
  }.

Definition semaphore۰Σ :=
  #[mutex۰Σ
  ; excl۰Σ unitO
  ].
#[global] Instance subGsemaphore۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG semaphore۰Σ Σ
  SemaphoreG Σ.

Section semaphore۰G.
  Context `{semaphore۰G : SemaphoreG Σ}.

  Implicit Type P : iProp Σ.

  Record metadata :=
    { metadata۰mutex : val
    ; metadata۰condition : val
    ; metadata۰tokens : list gname
    }.
  Implicit Type γ : metadata.
  Implicit Type γ_tokens : list gname.

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

  #[local] Definition tokens۰auth' γ_tokens cap : iProp Σ :=
    length γ_tokens = cap.
  #[local] Definition tokens۰auth γ :=
    tokens۰auth' γ.(metadata۰tokens).
  #[local] Instance : CustomIpat "tokens۰auth" :=
    " %Htokens ".
  #[local] Definition tokens۰frag' γ_tokens : iProp Σ :=
     i η,
    γ_tokens !! i = Some η
    excl η ().
  #[local] Definition tokens۰frag γ :=
    tokens۰frag' γ.(metadata۰tokens).
  #[local] Instance : CustomIpat "tokens۰frag" :=
    " ( %i & %η & %Htokens_lookup & Hexcl ) ".

  #[local] Definition inv۰inner l γ P : iProp Σ :=
     cnt,
    l.[count] #cnt
    [∗ list] _ seq 0 ˖cnt,
      tokens۰frag γ
      P.
  #[local] Instance : CustomIpat "inv۰inner" :=
    " ( %cnt & Hl_count & H ) ".
  Definition semaphore۰inv t cap P : iProp Σ :=
     l γ,
    t = #l
    l γ
    l.[mutex] γ.(metadata۰mutex)
    mutex۰inv γ.(metadata۰mutex) (inv۰inner l γ P)
    l.[condition] γ.(metadata۰condition)
    condition۰inv γ.(metadata۰condition)
    tokens۰auth γ cap.
  #[local] Instance : CustomIpat "inv" :=
    " ( %l & %γ & -> & #Hmeta & #Hl_mutex & #Hmutex_inv & #Hl_condition & #Hcondition_inv & #Htokens_auth ) ".

  Definition semaphore۰locked t : iProp Σ :=
     l γ,
    t = #l
    l γ
    tokens۰frag γ.
  #[local] Instance : CustomIpat "locked" :=
    " ( %l_ & %γ_ & %Heq & #Hmeta_ & Htokens_frag ) ".

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

  #[global] Instance semaphore۰lockedtimeless t :
    Timeless (semaphore۰locked t).

  #[local] Instance tokens۰authpersistent γ cap :
    Persistent (tokens۰auth γ cap).
  #[global] Instance semaphore۰invpersistent t cap P :
    Persistent (semaphore۰inv t cap P).

  #[local] Lemma tokensalloc cap :
     |==>
       γ_tokens,
      tokens۰auth' γ_tokens cap
      [∗ list] _ seq 0 cap, tokens۰frag' γ_tokens.
  #[local] Lemma tokens۰fragsvalid γ cap n :
    tokens۰auth γ cap -∗
    ([∗ list] _ seq 0 n, tokens۰frag γ) -∗
    n cap.

  Opaque tokens۰auth.
  Opaque tokens۰frag.

  Lemma semaphore٠createspec {cap} P :
    (0 < cap)%Z
    {{{
      [∗ list] _ seq 0 cap, P
    }}}
      semaphore٠create #cap
    {{{
      t
    , RET t;
      semaphore۰inv t cap P
    }}}.

  Lemma semaphore٠try_lockspec t cap P :
    {{{
      semaphore۰inv t cap P
    }}}
      semaphore٠try_lock t
    {{{
      b
    , RET #b;
      if b then
        semaphore۰locked t
        P
      else
        True
    }}}.

  Lemma semaphore٠lockspec t cap P :
    {{{
      semaphore۰inv t cap P
    }}}
      semaphore٠lock t
    {{{
      RET ();
      semaphore۰locked t
      P
    }}}.

  Lemma semaphore٠unlockspec t cap P :
    {{{
      semaphore۰inv t cap P
      semaphore۰locked t
      P
    }}}
      semaphore٠unlock t
    {{{
      RET ();
      True
    }}}.
End semaphore۰G.

Require zoo_std.semaphore__opaque.

#[global] Opaque semaphore۰inv.
#[global] Opaque semaphore۰locked.