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_LabeledParams : LabeledMultiParams LockServ_BaseParams :=
{
lb_name := Name ;
lb_msg  := Msg ;
lb_msg_eq_dec := Msg_eq_dec ;
lb_name_eq_dec := Name_eq_dec ;
lb_nodes := Nodes ;
lb_all_names_nodes := In_n_Nodes ;
lb_no_dup_nodes := nodup ;
label := Label ;
label_silent := Silent;
lb_init_handlers := init_data ;
lb_net_handlers := fun dst src msg s =>
runGenHandler s (NetHandler dst src msg) ;
lb_input_handlers := fun nm msg s =>
runGenHandler s (InputHandler nm msg)
}.
Global Instance LockServ_MultiParams : MultiParams LockServ_BaseParams :=
unlabeled_multi_params.
(* 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.