57 lines
1.6 KiB
Erlang
57 lines
1.6 KiB
Erlang
|
-module(ring).
|
||
|
|
||
|
%% erlc ring.erl; erl +P 10000000 -eval 'io:format("~p~n", [ring:start(1000000, 1000)]), init:stop()'
|
||
|
|
||
|
-export([start/2]).
|
||
|
|
||
|
start(NActors, NRounds) ->
|
||
|
io:format("Starting threads...~n"),
|
||
|
First = spawn1(NRounds),
|
||
|
Peers = [Last | _] = spawnN(NActors - 1, [First], NRounds),
|
||
|
First ! {peer, Last},
|
||
|
io:format("Starting measurement (~p processes)...~n", [length(Peers)]),
|
||
|
{Microseconds, ok} =
|
||
|
timer:tc(fun () ->
|
||
|
[P ! {hop, 0} || P <- Peers],
|
||
|
wait_for_all(NActors)
|
||
|
end),
|
||
|
Seconds = Microseconds / 1000000.0,
|
||
|
{ok, {{seconds, Seconds}, {hz, NActors * NRounds / Seconds}}}.
|
||
|
|
||
|
wait_for_all(0) ->
|
||
|
ok;
|
||
|
wait_for_all(Remaining) ->
|
||
|
receive
|
||
|
one_actor_done ->
|
||
|
wait_for_all(Remaining - 1)
|
||
|
end.
|
||
|
|
||
|
spawn1(NRounds) ->
|
||
|
Main = self(),
|
||
|
spawn(fun () -> forwarder_main(Main, NRounds) end).
|
||
|
|
||
|
spawnN(0, Peers, _NRounds) ->
|
||
|
Peers;
|
||
|
spawnN(Remaining, Peers = [Peer | _], NRounds) ->
|
||
|
A = spawn1(NRounds),
|
||
|
A ! {peer, Peer},
|
||
|
spawnN(Remaining - 1, [A | Peers], NRounds).
|
||
|
|
||
|
forwarder_main(MainActor, NRounds) ->
|
||
|
receive
|
||
|
{peer, Peer} ->
|
||
|
forwarder_main_loop(MainActor, Peer, NRounds)
|
||
|
end.
|
||
|
|
||
|
forwarder_main_loop(MainActor, Peer, NRounds) ->
|
||
|
receive
|
||
|
{hop, HopCount} ->
|
||
|
if
|
||
|
HopCount < NRounds - 1 ->
|
||
|
Peer ! {hop, HopCount + 1};
|
||
|
true ->
|
||
|
MainActor ! one_actor_done
|
||
|
end,
|
||
|
forwarder_main_loop(MainActor, Peer, NRounds)
|
||
|
end.
|