fib(N)->
P1 = spawn(fun concFib:conFib/0),
P2 = spawn(fun concFib:conFib/0),
X=rpc(P1,N-2),Y=rpc(P2,N-1),X+Y.
conFib()->
receive
{Client,N} -> Client ! regfib(N)
end.
rpc(Pid,Request)->
case erlang:is_process_alive(Pid) of
true -> begin
Pid ! {self(),Request},
receive
{Pid,Respond} -> Respond
end
end;
false -> io:format("~w process is dead.",[Pid])
end.
regfib(N)->
case N<2 of
true -> 1;
false -> regfib(N,1,1,1)
end.
regfib(N,N,X,_)-> X ;
regfib(N,M,X,Y)-> regfib(N,M+1,X+Y,X).
The idea is to divide the fib(N) process into two process one calculates fib(N-2) and the other one calc. fib(N-1) concurrently as fib(N)=fib(N-1)+fib(N-2). when i run the previous code nothing happen and the cursor stop as in finite loop or waiting for not arriving result.
plzzz i need help i'm a new Erlang programmer,thanks in advance :)
In your conFib you send an integer, but await a tuple in rpc. Should change it to:
conFib()->
receive
{Client,N} -> Client ! {self(), regfib(N)}
end.
You can evade such situations by using timeout with after in your receives.
To make the computation parallel you could do something like:
fib(N)->
P1 = spawn(fun test:conFib/0),
P2 = spawn(fun test:conFib/0),
P1 ! {self(), N - 2},
P2 ! {self(), N - 1},
receive
{_, R1} -> R1
end,
receive
{_, R2} -> R2
end,
R1 + R2.
The important part is that you send both of the requests before waiting for the answers.
The part waiting for the answers could of course be done in a more beautiful way.
Related
I have recently started learning Erlang and I am trying to implement a server-client sample program. I have created a registered process and I would like to send data to it from another process. The code is as follows.
-module(mine).
-export([alice/0, bob/2, startAlice/0, startBob/1]).
alice() ->
receive
{message, BobNode} ->
io:fwrite("Alice got a message \n"),
BobNode ! message,
alice()
finished -> io:fwrite("Alice is finished\n")
end.
bob(0, AliceNode) ->
{alice, AliceNode} ! finished,
io:fwrite("Bob is finished\n");
bob(N, AliceNode) ->
{alice, AliceNode} ! {message, self()},
receive
message -> io:fwrite("Bob got a message ~w \n",[N])
end,
bob(N-1, AliceNode).
startAlice() ->
register(alice, spawn(mine, alice, [])).
startBob(AliceNode) ->
spawn(mine, bob, [30000, AliceNode]).
Here, I would like to send some value say N, from bob to alice. I tried sending the data as
{alice, AliceNode, Nvalue} ! {message, self(), N} in bob(N, AliceNode) function, but got the error variable 'Nvalue' is unbound erl. I am sure I am missing something trivial here. Any help would be appreciated. Thanks in advance.
Is it possible to spawn a process p in a function funct1 of a module module1, to send a message to p in a function funct2 of module1 and to wait for a reply of p inside funct2, without having to spawn f2 that is therefore considered as self()? If so, what is the best way to implement the waiting part? You can see the code below to have an overview of what I am looking for.
Thanks in advance.
-module(module1)
...
funct1(...)
->
Pid = spawn(module2, function3, [[my_data]]),
...
funct2(...)
->
...
Pid ! {self(), {data1, data2}},
% wait here for the reply from Pid
% do something here based on the reply.
The Answer
Yes.
The Real Problem
You are conflating three concepts:
Process (who is self() and what is pid())
Function
Module
A process is a living thing. A process has its own memory space. These processes are the things making calls. This is the only identity that really matters. When you think about "who is self() in this case" you are really asking "what is the calling context?" If I spawn two instances of a process, they both might call the same function at some point in their lives -- but the context of those calls are completely different because the processes have their own lives and their own memory spaces. Just because Victor and Victoria are both jumping rope at the same time doesn't make them the same person.
Where people get mixed up about calling context the most is when writing module interface functions. Most modules are, for the sake of simplicity, written in a way that they define just a single process. There is no rule that mandates this, but it is pretty easy to understand what a module does when it is written this way. Interface functions are exported and available for any process to call -- and they are calling in the context of the processes calling them, not in the context of a process spawned to "be an instance of that module" and run the service loop defined therein.
There is nothing trapping a process "within" that module, though. I could write a pair of modules, one that defines the AI of a lion and another that defines the AI of a shark, and have a process essentially switch identities in the middle of its execution -- but this is almost always a really bad idea (because it gets confusing).
Functions are just functions. That's all they are. Modules are composed of functions. There is nothing more to say than this.
How to wait for a message
We wait for messages using the receive construct. It matches on the received message (which will always be an Erlang term) and selects what to do based on the shape and/or content of the message.
Read the following very carefully:
1> Talker =
1> fun T() ->
1> receive
1> {tell, Pid, Message} ->
1> ok = io:format("~p: sending ~p message ~p~n", [self(), Pid, Message]),
1> Pid ! {message, Message, self()},
1> T();
1> {message, Message, From} ->
1> ok = io:format("~p: from ~p received message ~p~n", [self(), From, Message]),
1> T();
1> exit ->
1> exit(normal)
1> end
1> end.
#Fun<erl_eval.44.87737649>
2> {Pid1, Ref1} = spawn_monitor(Talker).
{<0.64.0>,#Ref<0.1042362935.2208301058.9128>}
3> {Pid2, Ref2} = spawn_monitor(Talker).
{<0.69.0>,#Ref<0.1042362935.2208301058.9139>}
4> Pid1 ! {tell, Pid2, "A CAPITALIZED MESSAGE! RAAAR!"}.
<0.64.0>: sending <0.69.0> message "A CAPITALIZED MESSAGE! RAAAR!"
{tell,<0.69.0>,"A CAPITALIZED MESSAGE! RAAAR!"}
<0.69.0>: from <0.64.0> received message "A CAPITALIZED MESSAGE! RAAAR!"
5> Pid2 ! {tell, Pid1, "a lower cased message..."}.
<0.69.0>: sending <0.64.0> message "a lower cased message..."
{tell,<0.64.0>,"a lower cased message..."}
<0.64.0>: from <0.69.0> received message "a lower cased message..."
6> Pid1 ! {tell, Pid1, "Sending myself a message!"}.
<0.64.0>: sending <0.64.0> message "Sending myself a message!"
{tell,<0.64.0>,"Sending myself a message!"}
<0.64.0>: from <0.64.0> received message "Sending myself a message!"
7> Pid1 ! {message, "A direct message from the shell", self()}.
<0.64.0>: from <0.67.0> received message "A direct message from the shell"
{message,"A direct message from the shell",<0.67.0>}
A standalone example
Now consider this escript of a ping-pong service. Notice there is only one kind of talker defined inside and it knows how to deal with target, ping and pong messages.
#! /usr/bin/env escript
-mode(compile).
main([CountString]) ->
Count = list_to_integer(CountString),
ok = io:format("~p: Starting pingpong script. Will iterate ~p times.~n", [self(), Count]),
P1 = spawn_link(fun talker/0),
P2 = spawn_link(fun talker/0),
pingpong(Count, P1, P2).
pingpong(Count, P1, P2) when Count > 0 ->
P1 ! {target, P2},
P2 ! {target, P1},
pingpong(Count - 1, P1, P2);
pingpong(_, P1, P2) ->
_ = erlang:send_after(1000, P1, {exit, self()}),
_ = erlang:send_after(1000, P2, {exit, self()}),
wait_for_exit([P1, P2]).
wait_for_exit([]) ->
ok = io:format("~p: All done, Returing.~n", [self()]),
halt(0);
wait_for_exit(Pids) ->
receive
{exiting, Pid} ->
ok = io:format("~p: ~p is done.~n", [self(), Pid]),
NewPids = lists:delete(Pid, Pids),
wait_for_exit(NewPids)
end.
talker() ->
receive
{target, Pid} ->
ok = io:format("~p: Sending ping to ~p~n", [self(), Pid]),
Pid ! {ping, self()},
talker();
{ping, From} ->
ok = io:format("~p: Received ping from ~p. Replying with pong.~n", [self(), From]),
From ! pong,
talker();
pong ->
ok = io:format("~p: Received pong.~n", [self()]),
talker();
{exit, From} ->
ok = io:format("~p: Received exit message from ~p. Retiring.~n", [self(), From]),
From ! {exiting, self()}
end.
There are some details there, like use of erlang:send_after/3 that are used because message sending is so fast that it will beat the speed of the calls to io:format/2 that slow down the actual talker processes and result in a weird situation where the exit messages (usually) arrive before the pings and pongs between the two talkers.
Here is what happens when it is run:
ceverett#changa:~/Code/erlang$ ./pingpong 2
<0.5.0>: Starting pingpong script. Will iterate 2 times.
<0.61.0>: Sending ping to <0.62.0>
<0.62.0>: Sending ping to <0.61.0>
<0.61.0>: Sending ping to <0.62.0>
<0.62.0>: Sending ping to <0.61.0>
<0.61.0>: Received ping from <0.62.0>. Replying with pong.
<0.62.0>: Received ping from <0.61.0>. Replying with pong.
<0.61.0>: Received ping from <0.62.0>. Replying with pong.
<0.62.0>: Received ping from <0.61.0>. Replying with pong.
<0.61.0>: Received pong.
<0.62.0>: Received pong.
<0.61.0>: Received pong.
<0.62.0>: Received pong.
<0.61.0>: Received exit message from <0.5.0>. Retiring.
<0.62.0>: Received exit message from <0.5.0>. Retiring.
<0.5.0>: <0.61.0> is done.
<0.5.0>: <0.62.0> is done.
<0.5.0>: All done, Returing.
If you run it a few times (or on a busy runtime) there is a chance that some of the output will be in different order. That is just the nature of concurrency.
If you are new to Erlang the above code might take a while to sink in. Play with that pingpong script yourself. Edit it. Make it do new things. Create a triangle of pinging processes. Spawn a random circuit of talkers that do weird things. This will make sense suddenly once you mess around with it.
I'm basically following the tutorial on this site Learn you some Erlang:Designing a concurrent application and I tried to run the code below with the following commands and got an error on line 48. I did turn off my firewall just in case that was the problem but no luck. I'm on windows xp SP3.
9> c(event).
{ok,event}
10> f().
ok
11> event:start("Event",0).
=ERROR REPORT==== 9-Feb-2013::15:05:07 ===
Error in process <0.61.0> with exit value: {function_clause,[{event,time_to_go,[0],[{file,"event.erl"},{line,48}]},{event,init,3,[{file,"event.erl"},{line,31}]}]}
<0.61.0>
12>
-module(event).
-export([start/2, start_link/2, cancel/1]).
-export([init/3, loop/1]).
-record(state, {server,
name="",
to_go=0}).
%%% Public interface
start(EventName, DateTime) ->
spawn(?MODULE, init, [self(), EventName, DateTime]).
start_link(EventName, DateTime) ->
spawn_link(?MODULE, init, [self(), EventName, DateTime]).
cancel(Pid) ->
%% Monitor in case the process is already dead
Ref = erlang:monitor(process, Pid),
Pid ! {self(), Ref, cancel},
receive
{Ref, ok} ->
erlang:demonitor(Ref, [flush]),
ok;
{'DOWN', Ref, process, Pid, _Reason} ->
ok
end.
%%% Event's innards
init(Server, EventName, DateTime) ->
loop(#state{server=Server,
name=EventName,
to_go=time_to_go(DateTime)}).
%% Loop uses a list for times in order to go around the ~49 days limit
%% on timeouts.
loop(S = #state{server=Server, to_go=[T|Next]}) ->
receive
{Server, Ref, cancel} ->
Server ! {Ref, ok}
after T*1000 ->
if Next =:= [] ->
Server ! {done, S#state.name};
Next =/= [] ->
loop(S#state{to_go=Next})
end
end.
%%% private functions
time_to_go(TimeOut={{_,_,_}, {_,_,_}}) ->
Now = calendar:local_time(),
ToGo = calendar:datetime_to_gregorian_seconds(TimeOut) -
calendar:datetime_to_gregorian_seconds(Now),
Secs = if ToGo > 0 -> ToGo;
ToGo =< 0 -> 0
end,
normalize(Secs).
%% Because Erlang is limited to about 49 days (49*24*60*60*1000) in
%% milliseconds, the following function is used
normalize(N) ->
Limit = 49*24*60*60,
[N rem Limit | lists:duplicate(N div Limit, Limit)].
It's running purely locally on your machine so the firewall will not affect it.
The problem is the second argument you gave when you started it event:start("Event",0).
The error reason:
{function_clause,[{event,time_to_go,[0],[{file,"event.erl"},{line,48}]},{event,init,3,[{file,"event.erl"},{line,31}]}]}
says that it is a function_clause error which means that there was no clause in the function definition which matched the arguments. It also tells you that it was the function event:time_to_go/1 on line 48 which failed and that it was called with the argument 0.
It you look at the function time_to_go/ you will see that it expects its argument to be a tuple of 2 elements where each element is a tuple of 3 elements:
time_to_go(TimeOut={{_,_,_}, {_,_,_}}) ->
The structure of this argument is {{Year,Month,Day},{Hour,Minute,Second}}. If you follow this argument backwards you that time_to_go/ is called from init/3 where the argument to time_to_go/1, DateTime, is the 3rd argument to init/3. Almost there now. Now init/3 is the function which the process spawned in start/2 (and start_link/2) and the 3rd argument toinit/3is the second argument tostart/2`.
So when you call event:start("Event",0). it is the 0 here which is passed into the call time_to_go/1 function in the new peocess. And the format is wrong. You should be calling it with something like event:start("Event", {{2013,3,24},{17,53,62}}).
To add background to rvirding's answer, you get the error because the
example works up until the final code snippet as far
as I know. The normalize function is used first, which deals with the
problem. Then the paragraph right after the example in the question
above, the text says:
And it works! The last thing annoying with the event module is that we
have to input the time left in seconds. It would be much better if we
could use a standard format such as Erlang's datetime ({{Year, Month,
Day}, {Hour, Minute, Second}}). Just add the following function that
will calculate the difference between the current time on your
computer and the delay you inserted:
The next snippet introduces the code bit that takes only a date/time and
changes it to the final time left.
I could not easily link to all transitional versions of the file, which
is why trying the linked file directly with the example doesn't work
super easily in this case. If the code is followed step by step, snippet
by snippet, everything should work fine. Sorry for the confusion.
Simply put; how can I end a process if I accidentally forgot to equate a Pid variable when I started a process using this:
9> trivial_process:start().
<0.67.0>
10>
I know I should have written Pid = trivial_process:start(). Is there some way to take <0.67.0> and terminate the process?
-module(trivial_process).
-export([start/0]).
start() ->
spawn(fun() -> loop() end).
loop() ->
receive
Any ->
io:format("~nI got the message: ~p~n",[Any]),
loop()
end.
EDIT:Answer.
8> Pid = "<0.67.0>".
9> A2 = list_to_pid(Pid).
<0.67.0>
You can use the list_to_pid function. The docs are here. You shouldn't use this in deployed code, it's only useful for debugging. It doesn't work with remote pids, either.
Reference: Something maybe you don’t know about Erlang PIDs
My working environment is Erlang.
Can a process having 2 different functions have two receive blocks in the different functions.
receive
....
end.
request()
PID!(message)
%% Can i get the reply back here instead of the receive block above?
Yes, you can have many receive expressions. When one is evaluated it will take the first matching message out of the message queue/mailbox (take your pick of names) and leave the rest for the next receive. Sending a message, using the Pid ! Message syntax (the only way), is completely asynchronous and just adds the message to the end of the receiving processes message queue. receive is the only way to receive messages i.e. take them out of the message queue. You can never put them back.
There is no built-in synchronous message passing in Erlang, it is one by sending two messages:
The "requesting" process sends a message to the receiving process and then goes into a receive to wait for the reply.
The "receiving" process will itself get the message in a receive, process it, send the reply message back the the "requesting" process and then go into a receive to sit and wait for the next message.
Remember there is no inherent connection between processes, ever, and all communication is done using asynchronous message sending and receive.
So in reply to your second question: you can ONLY get a reply back in a receive expression. That is the only way!
Sorry to be a bit pedantic but Erlang doesn't have either blocks or statements. It is a functional language and only has expressions which always return a value even if the return value is sometimes ignored.
Of couse, you can.
Receives messages sent to the process using the send operator (!). The
patterns Pattern are sequentially matched against the first message in
time order in the mailbox, then the second, and so on. If a match
succeeds and the optional guard sequence GuardSeq is true, the
corresponding Body is evaluated. The matching message is consumed,
that is removed from the mailbox, while any other messages in the
mailbox remain unchanged.
The following code is from supervisor2.erl of rabbitmq project. It even uses nested receive statement. I have marked nested receive below.
terminate_simple_children(Child, Dynamics, SupName) ->
Pids = dict:fold(fun (Pid, _Args, Pids) ->
erlang:monitor(process, Pid),
unlink(Pid),
exit(Pid, child_exit_reason(Child)),
[Pid | Pids]
end, [], Dynamics),
TimeoutMsg = {timeout, make_ref()},
TRef = timeout_start(Child, TimeoutMsg),
{Replies, Timedout} =
lists:foldl(
fun (_Pid, {Replies, Timedout}) ->
{Reply, Timedout1} =
receive %% attention here
TimeoutMsg ->
Remaining = Pids -- [P || {P, _} <- Replies],
[exit(P, kill) || P <- Remaining],
receive {'DOWN', _MRef, process, Pid, Reason} -> %%attention here
{{error, Reason}, true}
end;
{'DOWN', _MRef, process, Pid, Reason} ->
{child_res(Child, Reason, Timedout), Timedout};
{'EXIT', Pid, Reason} ->
receive {'DOWN', _MRef, process, Pid, _} ->
{{error, Reason}, Timedout}
end
end,
{[{Pid, Reply} | Replies], Timedout1}
end, {[], false}, Pids),
timeout_stop(Child, TRef, TimeoutMsg, Timedout),
ReportError = shutdown_error_reporter(SupName),
[case Reply of
{_Pid, ok} -> ok;
{Pid, {error, R}} -> ReportError(R, Child#child{pid = Pid})
end || Reply <- Replies],
ok.