spawn without linking?
Sean Hinde
sean.hinde@REDACTED
Thu Apr 29 21:04:10 CEST 2004
>>
>
> Ah, but Joe, you changed the semantics. Sean had a timeout argument,
> which you don't. ;-)
>
> BTW, Sean, you should rethink the implementation of the timeout.
> I think it's better to start a timer and handle a timeout message.
> In your present implementation, the "timer" will restart anytime
> one of the servers responds, making it fuzzy what the timeout
> really means.
>
OK, again ! I kept the foldl to emphasise that we visit each sent
call exactly once while gathering results, so it has grown somewhat with
the addition of a second state.
%% @doc Call one or more gen_servers multiple times with different
%% queries concurrently. This is equivalent to calling
%% gen_server:call(Name, Request, Timeout) multiple times except that
%% they are handled concurrently.
%% </p>
%% It is assumed that the calling process can tolerate late result
%% messsages arriving after this routine has finished.
%%
%% @spec multi_call(Requests, Timeout::integer()) ->
%% {[{Name, Result}], [Failure]}
%% Requests = [{Name, Request}]
%% Name = pid() | atom()
%% Request = term()
%% Result = term()
%% Failure = pid() | atom()
multi_call(Requests, Timeout) when is_list(Requests),
is_integer(Timeout) ->
Mrefs = lists:map(fun({Name, Req}) ->
Mref = erlang:monitor(process, Name),
Name ! {'$gen_call', {self(), Mref}, Req},
{Name, Mref}
end, Requests),
Timer = erlang:start_timer(Timeout, self(), timeout),
Res = lists:foldl(
fun({Name, Mref}, {within_time, Succ, Fail}) ->
receive
{Mref, Reply} ->
demonitor(Mref),
{within_time, [{Name, Reply}|Succ], Fail};
{'DOWN', Mref, _, _, _} ->
{within_time, Succ, [Name|Fail]};
{timeout, Timer, timeout} ->
demonitor(Mref),
{outside_time, Succ, [Name|Fail]}
end;
({Name, Mref}, {outside_time, Succ, Fail}) ->
receive
{Mref, Reply} ->
demonitor(Mref),
{outside_time, [{Name, Reply}|Succ], Fail};
{'DOWN', Mref, _, _, _} ->
{outside_time, Succ, [Name|Fail]}
after 0 ->
demonitor(Mref),
{outside_time, Succ, [Name|Fail]}
end
end, {within_time, [],[]}, Mrefs),
case Res of
{within_time, Succ, Fail} ->
erlang:cancel_timer(Timer),
receive
{timeout, Timer, timeout} ->
{Succ, Fail}
after 0 ->
{Succ, Fail}
end;
{outside_time, Succ, Fail} ->
{Succ, Fail}
end.
demonitor(Mref) ->
erlang:demonitor(Mref),
receive
{'DOWN', Mref, _, _, _} ->
ok
after 0 ->
ok
end.
More information about the erlang-questions
mailing list