Proof using.
unfold Nodes, list_Clients.
apply NoDup_cons.
- in_crush. discriminate.
- apply NoDup_map_injective.
+ intros. congruence.
+ apply all_fin_NoDup.
Qed.
Global Instance LockServ_BaseParams : BaseParams :=
{
data   := Data ;
input  := Input ;
output := Output
}.
Global Instance LockServ_MultiParams : MultiParams LockServ_BaseParams :=
{
name := Name ;
msg  := Msg ;
msg_eq_dec := Msg_eq_dec ;
name_eq_dec := Name_eq_dec ;
nodes := Nodes ;
all_names_nodes := In_n_Nodes ;
no_dup_nodes := nodup ;
init_handlers := init_data ;
net_handlers := fun dst src msg s =>
runGenHandler_ignore s (NetHandler dst src msg) ;
input_handlers := fun nm msg s =>
runGenHandler_ignore s (InputHandler nm msg)
}.
(* This is the fundamental safety property of the system: No two different clients can (think they) hold the lock at once. *)
Definition mutual_exclusion (sigma : name -> data) : Prop :=
forall m n,
held (sigma (Client m)) = true ->
held (sigma (Client n)) = true ->
m = n.
(* The system enforces mutual exclusion at the server. Whenever a client believs it holds the lock, that client is at the head of the server's queue. *)
Definition locks_correct (sigma : name -> data) : Prop :=
forall n,
held (sigma (Client n)) = true ->
exists t,
queue (sigma Server) = n :: t.

(* We first show that this actually implies mutual exclusion. *)
Lemma locks_correct_implies_mutex :
forall sigma,
locks_correct sigma ->
mutual_exclusion sigma.