1-module(dummy_via). 2-export([reset/0, 3 register_name/2, 4 whereis_name/1, 5 unregister_name/1, 6 send/2]). 7 8 9reset() -> 10 P = whereis(?MODULE), 11 catch unlink(P), 12 Ref = erlang:monitor(process, P), 13 catch exit(P, kill), 14 receive {'DOWN',Ref,_,_,_} -> ok end, 15 Me = self(), 16 Pid = spawn_link(fun() -> 17 register(?MODULE, self()), 18 Me ! {self(), started}, 19 loop([]) 20 end), 21 receive 22 {Pid, started} -> 23 Pid 24 after 10000 -> 25 exit(timeout) 26 end. 27 28register_name(Name, Pid) when is_pid(Pid) -> 29 call({register_name, Name, Pid}). 30 31unregister_name(Name) -> 32 call({unregister_name, Name}). 33 34whereis_name(Name) -> 35 call({whereis_name, Name}). 36 37send(Name, Msg) -> 38 case whereis_name(Name) of 39 undefined -> 40 exit({badarg, {Name, Msg}}); 41 Pid when is_pid(Pid) -> 42 Pid ! Msg, 43 Pid 44 end. 45 46call(Req) -> 47 MRef = erlang:monitor(process, ?MODULE), 48 ?MODULE ! {self(), MRef, Req}, 49 receive 50 {'DOWN', MRef, _, _, _} -> 51 erlang:error(badarg); 52 {MRef, badarg} -> 53 erlang:demonitor(MRef), 54 erlang:error(badarg); 55 {MRef, Reply} -> 56 erlang:demonitor(MRef), 57 Reply 58 after 5000 -> 59 erlang:error(timeout) 60 end. 61 62loop(Reg) -> 63 receive 64 {'DOWN', _, _, P, _} when is_pid(P) -> 65 loop([X || {_,Pid,_} = X <- Reg, Pid =/= P]); 66 {From, Ref, Request} when is_pid(From), is_reference(Ref) -> 67 {Reply, NewReg} = handle_request(Request, Reg), 68 From ! {Ref, Reply}, 69 loop(NewReg) 70 end. 71 72handle_request({register_name, Name, Pid}, Reg) when is_pid(Pid) -> 73 case lists:keyfind(Name, 1, Reg) of 74 false -> 75 Ref = erlang:monitor(process, Pid), 76 {yes, [{Name, Pid, Ref}|Reg]}; 77 _ -> 78 {no, Reg} 79 end; 80handle_request({whereis_name, Name}, Reg) -> 81 case lists:keyfind(Name, 1, Reg) of 82 {_, Pid, _} -> 83 {Pid, Reg}; 84 false -> 85 {undefined, Reg} 86 end; 87handle_request({unregister_name, Name}, Reg) -> 88 case lists:keyfind(Name, 1, Reg) of 89 {_, _, Ref} -> 90 catch erlang:demonitor(Ref); 91 _ -> 92 ok 93 end, 94 {ok, lists:keydelete(Name, 1, Reg)}; 95handle_request(_, Reg) -> 96 {badarg, Reg}. 97