spawn without linking?

Sean Hinde sean.hinde@REDACTED
Fri Apr 23 00:32:52 CEST 2004


On 21 Apr 2004, at 04:20, Shawn Pearce wrote:

> Actually, it is that hard to do...  the OTP behaviors offer lots
> of well tested/debugging implementations which handle the border
> cases extremely well.  Which a naive quick implementation using
> just the basic spawn_link/* and trap_exit won't get quite right on
> the first few tries.
>
> OTP rocks for that reason alone... but yea, gen_server isn't the
> most "Erlang" way to write a server, but its the Erlang/OTP way.

How about this which I had fun writing today. It is almost Erlangish, 
and it is something like OTP, and it is exactly Joe's selective receive 
example. I can't decide whether it is ugly or profoundly beautiful.

Sean

%% Call a bunch of gen_servers with different requests in
%% parallel and return successes and failures. Any which
%% fail to answer within Timeout ms are included as failures.

%% We require that the calling process will continue to ignore
%% late answers

multi_call(Requests, Timeout) ->
     Mrefs = lists:map(
               fun({Name, Req}) ->
                       Mref = erlang:monitor(process, Name),
                       Name ! {'$gen_call', {self(), Mref}, Req},
                       {Name, Mref}
               end, Requests),
     get_results(Mrefs, [], [], Timeout, now()).

get_results([{Name, Mref}|T], Succ, Fail, Timeout, Now_at_start) ->
     Timeout_val = max(Timeout - (timer:now_diff(now(), Now_at_start) 
div 1000), 0),
     receive
         {Mref, Reply} ->
             erlang:demonitor(Mref),
             receive
                 {'DOWN', Mref, _, _, _} ->
                     get_results(T, [{Name, Reply}|Succ], Fail, Timeout, 
Now_at_start)
             after 0 ->
                     get_results(T, [{Name, Reply}|Succ], Fail, Timeout, 
Now_at_start)
             end;
         {'DOWN', Mref, _, _, _} ->
             get_results(T, Succ, [Name|Fail], Timeout, Now_at_start)
     after Timeout_val ->
             erlang:demonitor(Mref),
             get_results(T, Succ, [Name|Fail], Timeout, Now_at_start)
     end;
get_results([], Succ, Fail, _, _) ->
     {Succ, Fail}.

max(A, B) when A >= B -> A;
max(A, B)             -> B.




More information about the erlang-questions mailing list