1 2 3 4 5 6 7 8 9
10
Concurrent Programming
Exercise Booklet 8: Message Passing
Solutions to selected exercises (♦) are provided at the end of this document. Important: You should first try solving them before looking at the solutions. You will otherwise learn nothing.
Exercise 1. Implement the turnstile example given at the beginning of the course. You should have a
counter process and two turnstile processes. The turnstile thread should send a {bump} message to the counter thread so that the counter can increment its local counter. The counter should also support a {read,From} that sends back the value of the counter to the process with pid From.
start(N) -> %% Spawns a counter and N turnstile clients
C = spawn(?MODULE ,counter_server ,[0]),
[ spawn(?MODULE ,turnstile ,[C,50]) || _ <- lists:seq(1,N)], C.
counter_server(State) -> %% State is the current value of the counter complete.
turnstile(C,N) -> %% C is the PID of the counter, and N the number of complete. %% times the turnstile turns
Exercise 2. Implement a server that concatenates strings. It should follow the protocol given by the following atoms (which are sent to the server):
• {start}: client wishes to send a number of strings to be concatenated; • {add,S}: concatenate string S to the current result;
• {done,From}: done sending strings, send back result to From.
start () ->
S = spawn(?MODULE ,server ,[]),
[ spawn(?MODULE,client,[S]) || _ <- lists:seq(1,100000)].
client(S) -> %% S!{start ,self()}, S!{add,”h”,self()}, S!{add,”e”,self()}, S!{add,”l”,self()}, S!{add,”l”,self()}, S!{add,”o”,self()}, S!{done,self()}, receive
{S,Str} ->
io:format(“Done: ~p~s~n”,[self(),Str]) end.
server () -> complete.
Discuss
• What happens if multiple clients want to use the service?
• Modify your solution so that the server spawns “servlets” that help out individual clients.
Exercise 3. We wish to define a server that receives two types of messages from a client: “continue” and “counter”.
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
CS511 – Concurrent Programming Exercise Booklet 8
1
CS511 – Concurrent Programming Exercise Booklet 8
1. Each time the server receives the message “counter” it should display on the screen the number of times that it received the “continue” message since the last time it received the “counter” message.
2. Modify your solution so that the server, instead of printing the number on the screen, sends it back to the client which then prints the number of the screen himself.
Exercise 4. (♦) We wish to model a Timer that, when spawned, receives the frequency with which it
should generate ticks and the set of pids which should receive ticks (a message represented as the atom tick). For example, spawn(timer,timer,[100, [pid1,pid2,pid3,pid4]]) will initiate the timer process that will send a tick message every 100 milliseconds to pids pid1, pid2, pid3 and pid4.
Exercise 5. Modify your solution so that the Timer is initially created with an empty list of pids and that clients have to register in order to receive ticks. For that they need to communicate with the Timer
sending it a register message.
Exercise 6. Write a server that receives a number n and sends back a boolean indicating whether it is
prime or not. Provide two solutions, one where you define an ad-hoc client and server and another using the generic server seen in class.
Exercise 7. (♦) Implement the bar exercise (Exercise 1) from EB5. On Fridays the bar is usually full of men, therefore the owners would like to implement an access control mechanism in which one man can
enter for every two women.
1. Complete the template below:
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16
-module(bar). -compile(export_all).
start(W,M) ->
S=spawn(?MODULE ,server ,[0,0]), [spawn(?MODULE,woman,[S]) || _ <- lists:seq(1,W)], [spawn(?MODULE,man,[S]) || _ <- lists:seq(1,M)].
woman(S) -> % Reference to PID of server error(not_implemented).
man(S) -> % Reference to PID of server error(not_implemented).
server(Women,Men) -> % Counters for Women and Men error(not_implemented).
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15
-module(bar2). -compile(export_all).
start(W,M) ->
S=spawn(?MODULE ,server ,[0,0,false]), [spawn(?MODULE,woman,[S]) || _ <- lists:seq(1,W)], [spawn(?MODULE,man,[S]) || _ <- lists:seq(1,M)], spawn(?MODULE ,itGotLate ,[3000,S]).
itGotLate(Time,S) -> timer:sleep(Time), R=make_ref(), S!{self(),R,itGotLate}, receive
{S,R,ok} ->
2. Consider how to address that extension where it can get late (see details in EB5). Complete the template below:
2
1 2 3 4 5 6 7 8 9
10 11
Exercise 8. You are asked to implement a guessing game. A server receives requests to play the game from clients. These requests are of the form {From,Ref,start}, where From is the Pid of the client, Ref is a
reference number and start is an atom. The server should then:
1. spawn a “servlet” process that plays the game with the client; and 2. then receive new client requests.
Note that by spawning a servlet the server is always responsive to new game requests. The servlet should behave as follows:
• generate a pseudorandom number in the range [0,10];
• wait for guesses from the client of the form {Pid,Ref,Number}, where Pid is its Pid, Ref is a reference
number and Number is the number the client is guessing.
• answer each message, indicating whether the client has guessed (gotIt) or not (tryAgain).
The client should keep guessing random numbers. Once it has guessed correctly, both client and servlet simply ends their execution.
You can use the function rand:uniform(N) for generating random numbers between 1 and N. Also, you may include helper functions.
-module(gg). -compile(export_all).
start () ->
spawn(fun server/0).
server () -> exit(incomplete).
client(S) -> exit(incomplete).
Exercise 9. We wish to model a network of processes, called nodes, each of which holds some number of tokens. Each node has a list of the pids of its neighboring nodes. A timer process sends a tick to all nodes
in the system. Upon receiving this tick, each node passes on a copy of all its tokens to all its neighbors.
1 Solutions to Selected Exercises
Answer to exercise 4
CS511 – Concurrent Programming
Exercise Booklet 8
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
done end.
woman(S) -> % Reference to PID of server error(not_implemented).
man(S) -> % Reference to PID of server error(not_implemented).
server(Women,Men,false) -> error(not_implemented);
server(Women,Men,true) -> error(not_implemented);
% Counters for Women and Men, false=it % did not get late yet
% Counters for Women and Men, true= it got late
3
CS511 – Concurrent Programming
Exercise Booklet 8
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
-module(tick). -compile(export_all).
start(T) ->
L = [spawn(?MODULE,client,[]) || _ <- lists:seq(1,10)], spawn(?MODULE,timer,[T,L]).
timer(Frequency ,L) -> timer:sleep(Frequency),
[ Pid!{tick} || Pid <- L], timer(Frequency ,L).
client () -> receive
{tick} -> client()
end.
-module(b). -compile(export_all).
Answer to exercise 7
start(W,M) ->
S=spawn(?MODULE ,server ,[0]), [spawn(?MODULE,woman,[S]) || _ <- lists:seq(1,W)], [spawn(?MODULE,man,[S]) || _ <- lists:seq(1,M)].
woman(S) -> % Reference to PID of server S!{self(),woman}.
man(S) -> % Reference to PID of server Ref = make_ref(), S!{self(),Ref,man},
receive
{S,Ref,ok} -> ok
end.
server(Women) -> receive
{_From ,woman} -> server(Women+1);
{From , Ref , man} when From!{self(),Ref,ok}, server(Women -2)
end.
Women >1 ->
4