Tonio's Dev blog

Wednesday, November 25, 2009

I'm reading the Programming Erlang book by Joe Armstrong, and here is my own version of the 8.11.2 exercise solution. There are many available on the internet, and mine is definitively not more brillant than another.
The ring:benchmark/3 function creates a process ring of size N, sends M messages in the ring, and each of those messages will be passed around K times before being sen back to the sender.

The book is really good, it has been a long time since I had so much fun learning a new language.


-module(ring).
-export([benchmark/3]).

init(N) ->
FirstPid = spawn(fun() -> waitpid(N+1) end),
init(N,FirstPid,FirstPid).

init(0,Pid,FirstPid) ->
FirstPid ! Pid;
init(N,PrevPid,FirstPid) ->
NextPid = spawn(fun() -> ring_node(PrevPid,N) end),
init(N-1,NextPid,FirstPid).

waitpid(N) ->
receive
Pid ->
ring_node(Pid,N)
end.

ring_node(Pid,N) ->
receive
{Origin, 0, Value} ->
Origin ! Value,
ring_node(Pid,N);
{Origin, Ttl, Value} ->
Pid ! {Origin, Ttl-1, Value},
ring_node(Pid,N);
Other ->
io:format("Wrong message: ~w~n", [Other]),
ring_node(Pid,N)
end.

send(Ring,Pid,M,Message) ->
Ring ! {Pid, M, Message}.
benchmark(N,M,K) ->
Pid = init(N),
My = self(),
statistics(runtime),
statistics(wall_clock),
for(1,M,fun(I) -> send(Pid,My,K,{a,I}) end),
R = getresult([],M),
{_, T1} = statistics(runtime),
{_, T2} = statistics(wall_clock),
io:format("Time spent: system:~w, clock:~w~n",[T1,T2]),
R.

getresult(L,0) ->
L;
getresult(L,M) ->
receive
Value -> getresult([Value|L],M-1)
end.

for(N,N,F) -> [F(N)];
for(Y,N,F) -> [F(Y),for(Y+1,N,F)].


Note to self: I should learn how to insert code with some colors and stuff one day.

Labels: , ,