aboutsummaryrefslogblamecommitdiffstats
path: root/common/server.erl
blob: 67fb000d2baea3f68365f1732aff3a66a64c85b9 (plain) (tree)
1
2
3
4
5
6
7
8
9
10






                                                                                       
                                                    

                   
                                                              

                          
                                                         
 
                                  
                                               
 
                        
           
                                  
                                       

        
                       


                                    
 
                      
           
                          

                                                













                                                      

                         


                                                




                                                            
                                       

                         

                                               
               

        

                                    
                                      
                              
%%  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]).