Library zoo_std.mutex

Require Import zoo.prelude.
Require Import zoo.iris.base_logic.lib.excl.
Require Import zoo.base.
Require Export zoo_std.mutex__code.
Require Import zoo_std.mutex__types.
Require Import zoo.options.

Implicit Type b : bool.
Implicit Type l : location.
Implicit Type t fn : val.

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

Definition mutex۰Σ :=
  #[excl۰Σ unitO
  ].
#[global] Instance subGmutex۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG mutex۰Σ Σ
  MutexG Σ.

Section mutex۰G.
  Context `{mutex۰G : MutexG Σ}.

  #[local] Definition metadata :=
    gname.
  Implicit Type γ : metadata.

  #[local] Definition locked γ :=
    excl γ ().

  Definition mutex۰init t b : iProp Σ :=
     l γ,
    t = #l
    l γ
    l ↦ᵣ #b
    if b then True else locked γ.

  #[local] Definition inv۰inner l γ P : iProp Σ :=
     b,
    l ↦ᵣ #b
    match b with
    | true
        True
    | false
        locked γ
        P
    end.
  Definition mutex۰inv t P : iProp Σ :=
     l γ,
    t = #l
    l γ
    inv nroot (inv۰inner l γ P).

  Definition mutex۰locked t : iProp Σ :=
     l γ,
    t = #l
    l γ
    locked γ.

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

  #[global] Instance mutex۰inittimeless t b :
    Timeless (mutex۰init t b).
  #[global] Instance mutex۰lockedtimeless t :
    Timeless (mutex۰locked t).

  #[global] Instance mutex۰invpersistent t P :
    Persistent (mutex۰inv t P).

  Lemma mutex۰initexclusive t b1 b2 :
    mutex۰init t b1 -∗
    mutex۰init t b2 -∗
    False.
  Lemma mutex۰inittoinv {t b} P E :
    mutex۰init t b -∗
    (if b then True else P) ={E}=∗
    mutex۰inv t P.

  Lemma mutex۰lockedexclusive t :
    mutex۰locked t -∗
    mutex۰locked t -∗
    False.

  Lemma mutex٠createspecinit :
    {{{
      True
    }}}
      mutex٠create ()
    {{{
      t
    , RET t;
      mutex۰init t false
    }}}.
  Lemma mutex٠createspec P :
    {{{
      P
    }}}
      mutex٠create ()
    {{{
      t
    , RET t;
      mutex۰inv t P
    }}}.

  Lemma mutex٠create_lockspecinit :
    {{{
      True
    }}}
      mutex٠create_lock ()
    {{{
      t
    , RET t;
      mutex۰init t true
      mutex۰locked t
    }}}.
  Lemma mutex٠create_lockspec P :
    {{{
      True
    }}}
      mutex٠create_lock ()
    {{{
      t
    , RET t;
      mutex۰inv t P
      mutex۰locked t
    }}}.

  Lemma mutex٠lockspec t P :
    {{{
      mutex۰inv t P
    }}}
      mutex٠lock t
    {{{
      RET ();
      mutex۰locked t
      P
    }}}.
  Lemma mutex٠lockspecinit t :
    {{{
      mutex۰init t false
    }}}
      mutex٠lock t
    {{{
      RET ();
      mutex۰init t true
      mutex۰locked t
    }}}.

  Lemma mutex٠unlockspec t P :
    {{{
      mutex۰inv t P
      mutex۰locked t
      P
    }}}
      mutex٠unlock t
    {{{
      RET ();
      True
    }}}.
  Lemma mutex٠unlockspecinit t :
    {{{
      mutex۰init t true
      mutex۰locked t
    }}}
      mutex٠unlock t
    {{{
      RET ();
      mutex۰init t false
    }}}.

  Lemma mutex٠synchronizespec t P :
    {{{
      mutex۰inv t P
    }}}
      mutex٠synchronize t
    {{{
      RET ();
      True
    }}}.
  #[global] Instance mutex٠synchronizediaspec t P :
    DIASPEC
    {{
      mutex۰inv t P
    }}
      mutex٠synchronize t
    {{
      RET ();
      True
    }}.

  Lemma mutex٠protectspec Ψ t P fn :
    {{{
      mutex۰inv t P
      ( mutex۰locked t -∗
        P -∗
        WP fn () {{ v,
          mutex۰locked t
          P
          Ψ v
        }}
      )
    }}}
      mutex٠protect t fn
    {{{
      v
    , RET v;
      Ψ v
    }}}.
End mutex۰G.

Require zoo_std.mutex__opaque.

#[global] Opaque mutex۰init.
#[global] Opaque mutex۰inv.
#[global] Opaque mutex۰locked.