Section LockServ.
Variable num_Clients : nat.
Definition Client_index := (fin num_Clients).
Inductive Name :=
| Client : Client_index -> Name
| Server : Name.
Definition list_Clients := map Client (all_fin num_Clients).
Definition Name_eq_dec : forall a b : Name, {a = b} + {a <> b}.
decide equality. apply fin_eq_dec.
Qed.
Inductive Msg :=
| Lock   : Msg
| Unlock : Msg
| Locked : Msg.
Definition Msg_eq_dec : forall a b : Msg, {a = b} + {a <> b}.
decide equality.
Qed.
Definition Input := Msg.
Definition Output := Msg.
Record Data := mkData { queue : list Client_index ; held : bool }.
Definition init_data (n : Name) : Data := mkData [] false.
Definition Handler (S : Type) := GenHandler (Name * Msg) S Output unit.
Definition ClientNetHandler (i : Client_index) (m : Msg) : Handler Data :=
match m with
| Locked => (put (mkData [] true)) >> write_output Locked
| _ => nop
end.
Definition ClientIOHandler (i : Client_index) (m : Msg) : Handler Data :=
match m with
| Lock => send (Server, Lock)
| Unlock => data <- get ;;
when (held data) (put (mkData [] false) >> send (Server, Unlock))
| _ => nop
end.
Definition ServerNetHandler (src : Name) (m : Msg) : Handler Data :=
st <- get ;;
let q := queue st in
match m with
| Lock =>
match src with
| Server => nop
| Client c =>
when (null q) (send (src, Locked)) >> put (mkData (q++[c]) (held st))
end
| Unlock => match q with
| _ :: x :: xs => put (mkData (x :: xs) (held st)) >> send (Client x, Locked)
| _ => put (mkData [] (held st))
end
| _ => nop
end.
Definition ServerIOHandler (m : Msg) : Handler Data := nop.
Definition NetHandler (nm src : Name) (m : Msg) : Handler Data :=
match nm with
| Client c => ClientNetHandler c m
| Server   => ServerNetHandler src m
end.
Definition InputHandler (nm : Name) (m : Msg) : Handler Data :=
match nm with
| Client c => ClientIOHandler c m
| Server   => ServerIOHandler m
end.
Ltac handler_unfold :=
repeat (monad_unfold; unfold NetHandler,
InputHandler,
ServerNetHandler,
ClientNetHandler,
ClientIOHandler,
ServerIOHandler in *).
Definition Nodes := Server :: list_Clients.

Theorem In_n_Nodes :
forall n : Name, In n Nodes.