  ` ` The contents of this file are subject to the Erlang Public License ,
  Version 1.1 , ( the " License " ) ; you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved via the world wide web at /.
%% 
  Software distributed under the License is distributed on an " AS IS "
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%% 
  The Initial Developer of the Original Code is Ericsson Utvecklings AB .
  Portions created by Ericsson are Copyright 1999 ,  
%% AB. All Rights Reserved.''
%% 

%%
%% File:   timer_wheel.erl
  Author :    
  Date :    2010 - 09 - 10
%%

-module(timer_wheel).

-export([bench_args/2, run/3]).
-export([wheel/1,no_wheel/1]).

bench_args(Version, Conf) ->
    {_,Cores} = lists:keyfind(number_of_cores, 1, Conf),
	F = case Version of
		short -> 16;
		intermediate -> 40;
		long -> 125
	end,
	[[Wheel,N] || Wheel <- [wheel,no_wheel], N <- [F * Cores]].

run([wheel,N|_], _, _) ->
	test(N, fun recv_loop_after/2);
run([no_wheel,N|_], _, _) ->
	test(N, fun recv_loop/2).

wheel(N) ->
	test(N, fun recv_loop_after/2).

no_wheel(N) ->
	test(N, fun recv_loop/2).

test(N, Fun) ->
	Me = self(),
	Pids = [spawn_link(fun() -> handler(N - 1, Fun, Me) end) || _ <- lists:seq(1, N)],
	[Pid ! {init, Pids -- [Pid]} || Pid <- Pids],
	[Pid ! start || Pid <- Pids],
	[receive {Pid, done} -> ok end || Pid <- Pids],
	ok.

handler(N, Fun, Me) ->
	Others = receive {init, Pids} -> Pids end,
	receive start -> ok end,
	loop(Others, N, Fun, Me).

loop([], 0, _, Me) ->
	Me ! {self(), done};
loop([], N, Fun, Me) ->
	loop([], Fun(undefined, N), Fun, Me);
loop([Pid|Pids], N, Fun, Me) ->
	Pid ! {self(), ping},
	loop(Pids, Fun(Pid, N), Fun, Me).

recv_loop_after(_, 0) ->
	0;
recv_loop_after(Pid, N) ->
	receive
		{Pid, pong} -> N;
		{Other, ping} ->	Other ! {self(), pong},
							recv_loop_after(Pid, N - 1)
		after 1073741824 -> exit(self(), kill)
	end.

recv_loop(_, 0) ->
	0;
recv_loop(Pid, N) ->
	receive
		{Pid, pong} -> N;
		{Other, ping} ->	Other ! {self(), pong},
							recv_loop(Pid, N - 1)
	end.


 compliance with the License. You should have received a copy of the
 Erlang Public License along with this software. If not, it can be
 retrieved via the world wide web at /.
 
 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 the License for the specific language governing rights and limitations
 under the License.
 
 AB. All Rights Reserved.''
 

 File:   timer_wheel.erl

  ` ` The contents of this file are subject to the Erlang Public License ,
  Version 1.1 , ( the " License " ) ; you may not use this file except in
  Software distributed under the License is distributed on an " AS IS "
  The Initial Developer of the Original Code is Ericsson Utvecklings AB .
  Portions created by Ericsson are Copyright 1999 ,  

  Author :    
  Date :    2010 - 09 - 10

-module(timer_wheel).

-export([bench_args/2, run/3]).
-export([wheel/1,no_wheel/1]).

bench_args(Version, Conf) ->
    {_,Cores} = lists:keyfind(number_of_cores, 1, Conf),
	F = case Version of
		short -> 16;
		intermediate -> 40;
		long -> 125
	end,
	[[Wheel,N] || Wheel <- [wheel,no_wheel], N <- [F * Cores]].

run([wheel,N|_], _, _) ->
	test(N, fun recv_loop_after/2);
run([no_wheel,N|_], _, _) ->
	test(N, fun recv_loop/2).

wheel(N) ->
	test(N, fun recv_loop_after/2).

no_wheel(N) ->
	test(N, fun recv_loop/2).

test(N, Fun) ->
	Me = self(),
	Pids = [spawn_link(fun() -> handler(N - 1, Fun, Me) end) || _ <- lists:seq(1, N)],
	[Pid ! {init, Pids -- [Pid]} || Pid <- Pids],
	[Pid ! start || Pid <- Pids],
	[receive {Pid, done} -> ok end || Pid <- Pids],
	ok.

handler(N, Fun, Me) ->
	Others = receive {init, Pids} -> Pids end,
	receive start -> ok end,
	loop(Others, N, Fun, Me).

loop([], 0, _, Me) ->
	Me ! {self(), done};
loop([], N, Fun, Me) ->
	loop([], Fun(undefined, N), Fun, Me);
loop([Pid|Pids], N, Fun, Me) ->
	Pid ! {self(), ping},
	loop(Pids, Fun(Pid, N), Fun, Me).

recv_loop_after(_, 0) ->
	0;
recv_loop_after(Pid, N) ->
	receive
		{Pid, pong} -> N;
		{Other, ping} ->	Other ! {self(), pong},
							recv_loop_after(Pid, N - 1)
		after 1073741824 -> exit(self(), kill)
	end.

recv_loop(_, 0) ->
	0;
recv_loop(Pid, N) ->
	receive
		{Pid, pong} -> N;
		{Other, ping} ->	Other ! {self(), pong},
							recv_loop(Pid, N - 1)
	end.

