% chat_supervisor.erl % Copyright 2005 Michael Leonhard % All Rights Reserved. % http://tamale.net/ -module(chat_supervisor). -export([start/0, stop/0, supervisor_start/0, linkme/1, sender_process/3]). start() -> io:fwrite("% Chat Server~n% Copyright 2005 Michael Leonhard~n"), io:fwrite("% All Rights Reserved.~n% http://tamale.net/~n"), spawn(chat_supervisor, supervisor_start, []), ok. stop() -> try chat_supervisor ! begin_shutdown catch error:badarg -> io:fwrite("supervisor is not running~n") end, ok. supervisor_start() -> io:fwrite("supervisor ~w: starting~n", [self()]), process_flag(trap_exit, true), register(chat_supervisor, self()), DispatcherPID = spawn_link(chat_dispatcher, dispatcher_start, []), spawn_link(chat_acceptor, acceptor_start, []), supervisor_loop([DispatcherPID]). supervisor_end(PIDs) -> if length(PIDs) == 0 -> io:fwrite("supervisor ~w: clean shutdown. stopping~n", [self()]); true -> io:fwrite("supervisor: processes failed to stop ~w~n", [PIDs]), io:fwrite("supervisor ~w: stopping (killing all remaining linked processes)~n", [self()]) end, exit(shutdown). linkme(Name) -> chat_supervisor ! {linkme, self(), Name}. sender_process(PID, Message, MillisecondsDelay) -> receive after MillisecondsDelay -> try PID ! Message catch error:badarg -> io:fwrite("sender_process cannot deliver ~w to ~w~n", [Message, PID]) end end. send_message_after(PID, Message, MillisecondsDelay) -> spawn(chat_supervisor, sender_process, [PID, Message, MillisecondsDelay]). supervisor_loop(PIDs) -> receive begin_shutdown -> io:fwrite("supervisor: instructing subordinates to stop~n"), lists:foreach( fun(PID) -> PID ! stop end, PIDs), send_message_after(self(), stop_now, 2000), supervisor_loop(PIDs); stop_now -> supervisor_end(PIDs); {linkme, PID, Name} -> link(PID), io:fwrite("supervisor: linked ~w ~w~n", [Name, PID]), PIDs2 = [PID | PIDs], supervisor_loop(PIDs2); {'EXIT', PID, normal} -> io:fwrite("supervisor: process ~w exited normally~n", [PID]), PIDs2 = PIDs -- [PID], supervisor_loop(PIDs2); {'EXIT', PID, Reason} -> io:fwrite("supervisor: process ~w exited with reason ~w~n", [PID, Reason]), io:fwrite("supervisor: exiting (along with all linked processes)~n"), exit(Reason) end.