%% Inspired by "Programming Erlang", %% published by The Pragmatic Bookshelf. %% Copyrights apply to this code. %% We make no guarantees that this code is fit for any purpose. %% Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information. -module(server). -export([start/2, start/3, start_on_node/3, rpc/2]). start(Name, Mod) -> register(Name, spawn(fun() -> loop(Mod, Mod:init()) end)). start(Name, Mod, State) -> register(Name, spawn(fun() -> loop(Mod, State) end)). start_on_node(Node, Mod, State) -> spawn(Node, fun() -> loop(Mod, State) end). wait_response(_, Ref) -> receive {Ref, crash} -> exit(rpc); {Ref, ok, Response} -> Response end. rpc(Client, Request) -> Ref = make_ref(), Client ! {Ref, self(), Request}, wait_response(Client, Ref). loop(Mod, OldState) -> receive {From, Request} -> try Mod:handle(Request, OldState) of {Response, NewState} -> From ! {ok, Response}, loop(Mod, NewState) catch _: Why -> log_the_error(Request, Why), From ! {crash}, loop(Mod, OldState) end; {Ref, From, Request} when is_reference(Ref) -> try Mod:handle(Request, OldState) of {Response, NewState} -> From ! {Ref, ok, Response}, loop(Mod, NewState) catch _: Why -> log_the_error(Request, Why), From ! {Ref, crash}, loop(Mod, OldState) end; {'EXIT', From, Why} -> try Mod:handle({'EXIT', From, Why}, OldState) of NewState -> loop(Mod, NewState) catch _: Why -> log_the_error('EXIT', Why), loop(Mod, OldState) end end. log_the_error(Request, Why) -> io:format("Server request ~p ~n" "caused exception ~p~n", [Request, Why]).