1 % sets up a ring of N processes, a message is passed M times around the ring. 2 -module(ring_no_io). 3 -export([run_benchmark/2, loop/2, mloop/1, main/1]). 4 % builds a ring of N processes and send a message around the ring M times. 5 run_benchmark(N, M) -> 6 % io:format(">> Erlang R11B-5 here (N=~w, M=~w)!~n~n", [N, M]), 7 % spawn the other N-1 processes needed for the ring 8 LastP = lists:foldl(fun(S, Pid) -> spawn(?MODULE, loop, [N-S, Pid]) end, 9 self(), lists:seq(1, N-1)), 10 spawn(fun() -> [ LastP ! R || R <- lists:reverse(lists:seq(0, M-1)) ] end), 11 mloop(N). 12 % receive loop executed by the first N-1 processes in the ring 13 % - 'S' is the sequence number allowing us to keep track of a 14 % process' position in the ring 15 % - 'NextP' is the next process in the ring 16 % - 'R' is the round/message number, zero indicates that the processes 17 % should terminate; 18 loop(S, NextP) -> 19 receive 20 % the message number is above zero => forward the message to the next 21 % process in the ring 22 R when R > 0 -> NextP ! R, 23 % io:format(": Proc: ~8w, Seq#: ~w, Msg#: ~w ..~n", [self(), S, R]), 24 loop(S, NextP); 25 % the message number is zero => forward message and terminate 26 R when R =:= 0 -> NextP ! R; 27 % io:format("* Proc: ~8w, Seq#: ~w, Msg#: terminate!~n", [self(), S]); 28 % error: the message number is below zero => raise exception 29 R when R < 0 -> 30 erlang:error({"internal error", "invalid message number"}) 31 end. 32 % receive loop executed by the last (Nth) process; 33 % it won't forward any messages 34 mloop(S) -> 35 receive 36 R when R > 0 -> 37 % io:format("> Proc: ~8w, Seq#: ~w, Msg#: ~w ..~n", [self(), S, R]), 38 mloop(S); 39 0 -> void 40 % io:format("@ Proc: ~8w, Seq#: ~w, ring terminated.~n", [self(), S]) 41 end. 42 % 'main' function allowing the invocation from the shell as well as the 43 % passing of command line arguments 44 main(A) -> 45 Args = [ list_to_integer(Litem) || 46 Litem <- [ atom_to_list(Atom) || Atom <- A ]], 47 [N, M] = Args, 48 run_benchmark(N, M).