summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam Kocoloski <adam@cloudant.com>2010-04-30 22:51:07 -0400
committerAdam Kocoloski <adam@cloudant.com>2010-04-30 22:51:07 -0400
commit09a9e6e6e88974b5bcc91a35275b71a104846674 (patch)
treeea963bf3c44f5c51546536898010d5085e7c3256 /src
parentd02f6cf7a4857ba902884c7d3e29ae8ac65cb698 (diff)
better abstraction in rexi_server
Diffstat (limited to 'src')
-rw-r--r--src/rexi_server.erl52
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}.