-module(cooperate).
-compile(export_all).
producer(_Pid, 0) ->
done;
producer(Pid, N) ->
Pid ! {producer, N},
io:format("process ~p producing ~p~n", [self(), rand:uniform(N)]),
producer(Pid, N-1).
consumer() ->
receive
{producer,Pid} ->
timer:sleep(10),io:format("process ~p consuming ~p~n", [self(), Pid]),
consumer()
after 40 ->
stopping_terminus
end.
go() ->
Pid = spawn(cooperate, consumer, []),
spawn(cooperate, producer, [Pid, 3]).
Expecting:
process <x.xx.x> producing 2
process <x.xx.x> producing 100
process <x.xx.x> producing 555
process <x.xx.x> consuming 2
process <x.xx.x> consuming 100
process <x.xx.x> consuming 555
I successfully producing random number like 2, 100, 555. Now, I want to sent the message to consumer and print them out. By the code above, I can only print consuming 3,2,1 due to the producer(Pid, N-1).
This line:
Pid ! {producer, N},
sends the message {producer, N}
to the consumer. For example, the consumer will receive a message like {producer, 3}
. You should be aware that in the consumer's receive statement:
receive
{producer,Pid} ->
Pid
will not match a pid. Just because you name a variable Pid, does not mean that it will actually match a pid. A pid is its own type in erlang--it is not an integer. A pid looks like the following when printed in the shell:
<0.83.0>
In your receive, Pid
will actually match N
, and N
is not a pid, rather N
is just an integer you pass as an argument. Do not name variables Pid
that do not actually match a pid.
If you want the producer to send a random number to the consumer, how would you do that? Well, you need the producer to send a message like {producer, SomeRandomNumber}
. How do you do that?
Pid ! {producer, SomeRandomNumber}
If the consumer needs to distinguish between the messages that contain N
and the messages that contain SomeRandomNumber
, then you can send the messages like this:
Pid ! {producer, producer_id, N}
Pid ! {producer, rand_num, SomeRandomNumber}
( or even Pid ! {producer, N, SomeRandomNumber}
)
Then in the consumer's receive statement, you can use matching to do different things for the different types of messages that the consumer receives:
receive
{producer, producer_id, N} ->
io:format("consumer ~p received message from producer ~p~n", [self(), N]),
consumer();
{producer, rand_num, SomeRandomNumber} ->
io:format("consumer ~p got random number ~p~n", [self(), SomeRandomNumber]),
consumer()
after 40 ->
stopping_terminus
end.