Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Erlang is there any way that a message sender can wait on a response?

Tags:

erlang

pid

actor

In Erlang is there any way that a message sender can wait on a response, so it only continues execution once the message has been processed?

And I mean something like this:

Actor ! DoSomething
Continue to this next line of code when DoSomething has been processed

I know a callback can be made by sending the Pid of the sender, but is there any other way to wait?

like image 999
yazz.com Avatar asked Feb 22 '10 17:02

yazz.com


People also ask

What does spawn do in Erlang?

spawn() creates a new process and returns the pid. The new process starts executing in Module:Name(Arg1,...,ArgN) where the arguments are the elements of the (possible empty) Args argument list. There exist a number of different spawn BIFs: spawn/1,2,3,4.

What is Erlang processes?

Erlang processes are lightweight, operate in (memory) isolation from other processes, and are scheduled by Erlang's Virtual Machine (VM). The creation time of process is very low, the memory footprint of a just spawned process is very small, and a single Erlang VM can have millions of processes running.

How do I stop Erlang process?

A process can terminate itself by calling one of the BIFs exit(Reason), erlang:error(Reason), erlang:error(Reason, Args), erlang:fault(Reason) or erlang:fault(Reason, Args). The process then terminates with reason Reason for exit/1 or {Reason,Stack} for the others.

Which module is used to spawn processes manually in Erlang?

The Erlang BIF spawn is used to create a new process: spawn(Module, Exported_Function, List of Arguments).


1 Answers

First thing to understand is that Erlang was built to deal with asynchronous message passing. As such, the only way to have synchronous message passing is to implement something akin to an acknowledgement.

Imagine two processes, P1 and P2. P1 might run the following code:

%% process P1 takes the Pid of P2 as a parameter
%% and a Message to pass on to P2
p1(P2, Message) ->
    P2 ! {self(), Message},
    receive
        {P2, ok}
    after 5000 -> % this section is optional, times out after 5s
        exit("P2 didn't process this!") % this kills P1
    end.

P2, on its side might just run the following:

p2() ->
    receive
        {From, Message} ->
            io:format("P2 received message ~p~n",[Message]),
            %% processing is done!
            From ! {self(), ok}
    end.

So then you might spawn p2 as a new process. This one will sit waiting for any message. When you then call p1, it sends a message to P2, which then processes it (io:format/2) and replies to P1. Because P1 was waiting for a reply, no additional code was run inside that process.

That's the basic and only way to implement blocking calls. The suggestions to use gen_server:call roughly implement what I've just shown. It's hidden from the programmer, though.

like image 89
I GIVE TERRIBLE ADVICE Avatar answered Nov 16 '22 00:11

I GIVE TERRIBLE ADVICE