[erlang-questions] Calling multiple processes simultaneously
Geoff Cant
nem@REDACTED
Mon May 23 22:20:23 CEST 2011
gen_server:call boils down to
call(Server, Msg, Timeout) ->
Ref = monitor(Server), % or make_ref()
Server ! {'$gen_call$', {self(), Ref}, Msg},
receive
{Ref, Reply} -> Reply
{'DOWN', Ref, _, _, Reason} -> exit(Reason)
after Timeout ->
exit(timeout)
end.
If you do:
barrier(Servers, Msg) -> [ gen_server:call(S, Msg) || S <- Servers ],
ok.
Then you'll wait at least Servers*2 message delays, and at worst Servers
* the gen_server call default timeout (5s).
You could do all the calls concurrently with something like:
call(Servers, Msg, Timeout) ->
Refs = [{S, monitor(S)}|| S <- Servers],
[S ! {'$gen_call$', {self(), Ref}, Msg}
|| {S, Ref} <- Refs ],
collect_replies(Refs, Timeout).
collect_replies([], _) -> [];
collect_replies([{S, Ref} | Rest], Timeout) ->
receive
{Ref, Reply} -> [{S, Reply} | collect_replies(Rest, Timeout)];
{'DOWN', Ref, _, _, Reason} -> [{S, {error, Reason}} |
collect_replies(Rest, Timeout)]
after Timeout ->
%% Timeout is now expired for all servers.
[{S, {error, timeout}} | collect_replies(Rest, 0)]
end.
This contains a basic attempt to not wait N*Timeout at worst, but could
be made closer to 1 timeout max by measuring the time from entering
collect_replies to receiving a Ref message and subtracting that from
Timeout before recurring.
This code doesn't handle all the special cases that gen:call does (
https://github.com/erlang/otp/blob/master/lib/stdlib/src/gen.erl#L191 ),
but should illustrate the idea.
--
Geoff Cant
Martin Dimitrov <mrtndimitrov@REDACTED> writes:
> Hi, please, advise on this one,
>
> We have several hundred processes (gen_servers) . At one point the
> program has to send them a message that needs to be handled before the
> calling process can continue executing. This naturally led us to use
> gen_server:call in loop over the processes.
>
> I started to wonder if there is a more efficient way of doing it since
> the calling process doesn’t care about the return value – just needs to
> be sure that all processes had handled the message. Can we somehow call
> the processes simultaneously? Something similar to gen_server:multi_call
> but for one node with different processes?
>
> Regards,
>
> Martin
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
More information about the erlang-questions
mailing list