diff options
author | Adam Kocoloski <adam@cloudant.com> | 2010-04-30 22:51:07 -0400 |
---|---|---|
committer | Adam Kocoloski <adam@cloudant.com> | 2010-04-30 22:51:07 -0400 |
commit | 09a9e6e6e88974b5bcc91a35275b71a104846674 (patch) | |
tree | ea963bf3c44f5c51546536898010d5085e7c3256 /src | |
parent | d02f6cf7a4857ba902884c7d3e29ae8ac65cb698 (diff) |
better abstraction in rexi_server
Diffstat (limited to 'src')
-rw-r--r-- | src/rexi_server.erl | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/src/rexi_server.erl b/src/rexi_server.erl index 0e443607..65110535 100644 --- a/src/rexi_server.erl +++ b/src/rexi_server.erl @@ -3,12 +3,12 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --export([start_link/0]). +-export([start_link/0, init_p/2]). -include_lib("eunit/include/eunit.hrl"). -record(st, { - field = value + workers = [] }). start_link() -> @@ -17,17 +17,47 @@ start_link() -> init([]) -> {ok, #st{}}. -handle_call(_Request, _From, State) -> - {reply, ok, State}. +handle_call(_Request, _From, St) -> + {reply, ok, St}. -handle_cast(_Msg, State) -> - {noreply, State}. +handle_cast({doit, From, MFA}, #st{workers=Workers} = St) -> + {LocalPid, Ref} = spawn_monitor(?MODULE, init_p, [From, MFA]), + {noreply, St#st{workers = add_worker({LocalPid, Ref, From}, Workers)}}. -handle_info(_Info, State) -> - {noreply, State}. +handle_info({'DOWN', Ref, process, _, normal}, #st{workers=Workers} = St) -> + {noreply, St#st{workers = remove_worker(Ref, Workers)}}; -terminate(_Reason, _State) -> +handle_info({'DOWN', Ref, process, Pid, Reason}, #st{workers=Workers} = St) -> + case find_worker(Ref, Workers) of + {Pid, Ref, From} -> + notify_caller(From, Pid, Reason); + false -> ok end, + {noreply, St#st{workers = remove_worker(Ref, Workers)}}; + +handle_info(_Info, St) -> + {noreply, St}. + +terminate(_Reason, St) -> + [exit(Pid,kill) || {Pid, _, _} <- St#st.workers], ok. -code_change(_OldVsn, State, _Extra) -> - {ok, State}. +code_change(_OldVsn, St, _Extra) -> + {ok, St}. + +init_p(From, {M,F,A}) -> + put(rexi_from, From), + try apply(M, F, A) catch _:Reason -> exit(Reason) end. + +%% internal + +add_worker(Worker, List) -> + [Worker | List]. + +remove_worker(Ref, List) -> + lists:keydelete(Ref, 2, List). + +find_worker(Ref, List) -> + lists:keyfind(Ref, 2, List). + +notify_caller({Caller, CallerRef}, Pid, Reason) -> + Caller ! {worker_died, CallerRef, Pid, Reason}. |