[erlang-questions] Calling multiple processes simultaneously

Joe Armstrong <>
Tue May 24 08:55:33 CEST 2011


You've just invented pmap :-) - this way of doing it obscures the logic of
what's going on:

   pmap(fun() -> gen_server:call(...) end, Pids)

All the round-trips to the server are done "almost in parallel" (assuming
spawn in the initial loop
is faster than the round-trip time to call a server) the execution time for
this should be O(T) where
T is the longest time for any server to reply.

pmap/2 is on page 366 of my Erlang book in the module lib_misc.erl

<hint>I put all small functions that are generally useful, and do not belong
to any particular module
in lib_misc.erl</hint>


pmap(F, L) ->
    S = self(),
    %% make_ref() returns a unique reference
    %%   we'll match on this later
    Ref = erlang:make_ref(),
    Pids = map(fun(I) ->
                       spawn(fun() -> do_f(S, Ref, F, I) end)
               end, L),
    %% gather the results
    gather(Pids, Ref).

do_f(Parent, Ref, F, I) ->
    Parent ! {self(), Ref, (catch F(I))}.

gather([Pid|T], Ref) ->
    receive
        {Pid, Ref, Ret} -> [Ret|gather(T, Ref)]
    end;
gather([], _) ->
    [].

/Joe


On Mon, May 23, 2011 at 10:50 PM, Edmond Begumisa <
> wrote:

> Another option...
>
> call_gen_servers(Pids) ->
>    Ref = erlang:make_ref(),
>    Caller = self(),
>    lists:foreach(fun(P) ->
>                    spawn_link(fun() ->
>                                    {reply, ok, _} = gen_server:call(foo,
> bar),
>                                    Caller ! {self(), Ref}
>                               end).
>                  end, Pids),
>    ok = wait_gen_servers(length(Pids), Ref).
>
> wait_gen_servers(0, _) ->
>    ok;
> wait_gen_servers(N, Ref) ->
>    receive
>        {_, Ref} ->
>            wait_gen_servers(N-1, Ref)
>    end.
>
> You could also add the timeout.
>
> - Edmond -
>
>
> On Tue, 24 May 2011 02:01:23 +1000, Martin Dimitrov <
> > wrote:
>
>  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
>> 
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
>
> --
> Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20110524/40097e12/attachment.html>


More information about the erlang-questions mailing list