gf.erl:
-module(gf).
-behavior(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([start/0, allocate/0, deallocate/1, stop/0, client/2, test1/0, test2/0]).
-export([cast_report/0, call_report/0]).
%%====== Server Internal function Replacements ==========
init([]) ->
{ok, {get_frequencies(), []} }.
get_frequencies() -> [10,11,12,13,14,15].
handle_call(call_report, _Pid, Freqs) ->
{reply, Freqs, Freqs};
handle_call(allocate, Client, Freqs) ->
{NewFreqs, Response} = allocate(Freqs, Client),
io:format("handle_call(allocate):~n \tFreqs: ~lp~n \tNewFreqs: ~lp~n~n",
[Freqs, NewFreqs]),
{reply, {reply, Response}, NewFreqs}.
handle_cast(cast_report, {Free, Taken}=Freqs) ->
io:format("\nhandle_cast(cast_report):\n===REPORT===~nFree: ~lp~nTaken: ~lp~n",
[Free, Taken]),
io:format("----------~n"),
{noreply, Freqs};
handle_cast({deallocate, Freq}, Freqs) ->
NewFreqs = deallocate(Freqs, Freq),
io:format("handle_cast(deallocate):~n \tFreqs: ~lp~n \tNewFreqs: ~lp~n~n",
[Freqs, NewFreqs]),
{noreply, NewFreqs};
handle_cast(stop, Freqs) ->
{stop, normal, Freqs}.
terminate(Reason, State) ->
io:format("~n~n<====== My Gen Frequency Server Shutdown ======>~n"),
io:format("Reason: ~w~n", [Reason]),
io:format("Ending Freqs:~n \t~lp~n", [State]).
%%Template:
%handle_cast({reset,N}, _State) ->
% {noreply, N}.
handle_info(_Info, State) ->
{noreply, State}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%% ----- No changes to server helper functions -----
allocate({[], Allocated}, _Pid) ->
{{[], Allocated}, {error, no_frequency}};
allocate({[Freq|Free], Allocated}, Pid) ->
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
deallocate({Free, Allocated}, Freq) ->
NewAllocated=lists:keydelete(Freq, 1, Allocated),
{[Freq|Free], NewAllocated}.
%%==== Server External function Replacements ===
start() ->
gen_server:start_link(
{local, ?MODULE},
?MODULE, [], []
).
allocate() ->
{reply, Response} = gen_server:call(?MODULE, allocate),
io:format("client: allocate(): Response: ~w~n", [Response]),
Response.
deallocate(Freq) ->
gen_server:cast(?MODULE, {deallocate, Freq}),
io:format("client: deallocate(): async deallocate(~w) request sent to gen_server~n",
[Freq]).
cast_report() ->
gen_server:cast(?MODULE, cast_report).
call_report() ->
{Free, Taken} = gen_server:call(?MODULE, call_report),
io:format("\ncall_report():\n===REPORT===~nFree: ~w~nTaken: ~w~n",
[Free, Taken]),
io:format("----------~n").
stop() ->
gen_server:cast(?MODULE, stop),
io:format("stop(): ansync stop request sent to gen_server~n").
%%===== TESTS =======
test2() ->
start(),
_Client1 = spawn(?MODULE, client, [1, 1000]),
_Client2 = spawn(?MODULE, client, [2, 2000]),
_Client3 = spawn(?MODULE, client, [3, 3000]),
timer:sleep(3000), %%Let clients go at it for awhile
call_report(),
timer:sleep(2000),
cast_report(),
timer:sleep(2000),
stop().
test1() ->
start(),
allocate_loop(8).
allocate_loop(0) ->
ok;
allocate_loop(N) ->
allocate(),
allocate_loop(N-1).
%%======= CLIENT =========
client(Id, Sleep) ->
handle_allocate_response(allocate(), Id, Sleep),
client(Id, Sleep).
handle_allocate_response({error, no_frequency}, Id, Sleep) ->
timer:sleep(500), %Sleep for a short time before trying again.
client(Id, Sleep);
handle_allocate_response({ok,Freq}, Id, Sleep) ->
timer:sleep(Sleep),
deallocate(Freq),
client(Id, Sleep).
In the shell:
$ ./run.sh
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
handle_call(allocate):
Freqs: {[10,11,12,13,14,15],[]}
NewFreqs: {[11,12,13,14,15],[{10,{<0.58.0>,#Ref<0.0.1.100>}}]}
handle_call(allocate):
Freqs: {[11,12,13,14,15],[{10,{<0.58.0>,#Ref<0.0.1.100>}}]}
NewFreqs: {[12,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.101>}},
{10,{<0.58.0>,#Ref<0.0.1.100>}}]}
client: allocate(): Response: {ok,10}
handle_call(allocate):
Freqs: {[12,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.101>}},
{10,{<0.58.0>,#Ref<0.0.1.100>}}]}
NewFreqs: {[13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.102>}},
{11,{<0.59.0>,#Ref<0.0.1.101>}},
{10,{<0.58.0>,#Ref<0.0.1.100>}}]}
client: allocate(): Response: {ok,11}
client: allocate(): Response: {ok,12}
Eshell V8.2 (abort with ^G)
1> client: deallocate(): async deallocate(10) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.102>}},
{11,{<0.59.0>,#Ref<0.0.1.101>}},
{10,{<0.58.0>,#Ref<0.0.1.100>}}]}
NewFreqs: {[10,13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.102>}},
{11,{<0.59.0>,#Ref<0.0.1.101>}}]}
handle_call(allocate):
Freqs: {[10,13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.102>}},
{11,{<0.59.0>,#Ref<0.0.1.101>}}]}
NewFreqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.117>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}},
{11,{<0.59.0>,#Ref<0.0.1.101>}}]}
client: allocate(): Response: {ok,10}
client: deallocate(): async deallocate(11) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.117>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}},
{11,{<0.59.0>,#Ref<0.0.1.101>}}]}
NewFreqs: {[11,13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.117>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}}]}
handle_call(allocate):
Freqs: {[11,13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.117>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}}]}
NewFreqs: {[13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.122>}},
{10,{<0.58.0>,#Ref<0.0.1.117>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}}]}
client: allocate(): Response: {ok,11}
client: deallocate(): async deallocate(10) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.122>}},
{10,{<0.58.0>,#Ref<0.0.1.117>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}}]}
NewFreqs: {[10,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.122>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}}]}
handle_call(allocate):
Freqs: {[10,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.122>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}}]}
NewFreqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.127>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}}]}
client: allocate(): Response: {ok,10}
call_report():
===REPORT===
Free: [13,14,15]
Taken: [{10,{<0.58.0>,#Ref<0.0.1.127>}},{11,{<0.59.0>,#Ref<0.0.1.122>}},{12,{<0.60.0>,#Ref<0.0.1.102>}}]
----------
client: deallocate(): async deallocate(12) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.127>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}},
{12,{<0.60.0>,#Ref<0.0.1.102>}}]}
NewFreqs: {[12,13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.127>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}}]}
handle_call(allocate):
Freqs: {[12,13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.127>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}}]}
NewFreqs: {[13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.135>}},
{10,{<0.58.0>,#Ref<0.0.1.127>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}}]}
client: allocate(): Response: {ok,12}
client: deallocate(): async deallocate(10) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.135>}},
{10,{<0.58.0>,#Ref<0.0.1.127>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}}]}
NewFreqs: {[10,13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.135>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}}]}
handle_call(allocate):
Freqs: {[10,13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.135>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}}]}
NewFreqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.140>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}}]}
client: allocate(): Response: {ok,10}
client: deallocate(): async deallocate(11) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.140>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}},
{11,{<0.59.0>,#Ref<0.0.1.122>}}]}
NewFreqs: {[11,13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.140>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
handle_call(allocate):
Freqs: {[11,13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.140>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
NewFreqs: {[13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.145>}},
{10,{<0.58.0>,#Ref<0.0.1.140>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
client: allocate(): Response: {ok,11}
client: deallocate(): async deallocate(10) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.145>}},
{10,{<0.58.0>,#Ref<0.0.1.140>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
NewFreqs: {[10,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
handle_call(allocate):
Freqs: {[10,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
NewFreqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.150>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
client: allocate(): Response: {ok,10}
handle_cast(cast_report):
===REPORT===
Free: [13,14,15]
Taken: [{10,{<0.58.0>,#Ref<0.0.1.150>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]
----------
client: deallocate(): async deallocate(10) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.150>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
NewFreqs: {[10,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
handle_call(allocate):
Freqs: {[10,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
NewFreqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.157>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
client: allocate(): Response: {ok,10}
client: deallocate(): async deallocate(12) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.157>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}},
{12,{<0.60.0>,#Ref<0.0.1.135>}}]}
NewFreqs: {[12,13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.157>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}}]}
handle_call(allocate):
Freqs: {[12,13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.157>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}}]}
NewFreqs: {[13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.162>}},
{10,{<0.58.0>,#Ref<0.0.1.157>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}}]}
client: allocate(): Response: {ok,12}
client: deallocate(): async deallocate(11) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.162>}},
{10,{<0.58.0>,#Ref<0.0.1.157>}},
{11,{<0.59.0>,#Ref<0.0.1.145>}}]}
NewFreqs: {[11,13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.162>}},
{10,{<0.58.0>,#Ref<0.0.1.157>}}]}
handle_call(allocate):
Freqs: {[11,13,14,15],
[{12,{<0.60.0>,#Ref<0.0.1.162>}},
{10,{<0.58.0>,#Ref<0.0.1.157>}}]}
NewFreqs: {[13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.167>}},
{12,{<0.60.0>,#Ref<0.0.1.162>}},
{10,{<0.58.0>,#Ref<0.0.1.157>}}]}
client: allocate(): Response: {ok,11}
client: deallocate(): async deallocate(10) request sent to gen_server
handle_cast(deallocate):
Freqs: {[13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.167>}},
{12,{<0.60.0>,#Ref<0.0.1.162>}},
{10,{<0.58.0>,#Ref<0.0.1.157>}}]}
NewFreqs: {[10,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.167>}},
{12,{<0.60.0>,#Ref<0.0.1.162>}}]}
handle_call(allocate):
Freqs: {[10,13,14,15],
[{11,{<0.59.0>,#Ref<0.0.1.167>}},
{12,{<0.60.0>,#Ref<0.0.1.162>}}]}
NewFreqs: {[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.172>}},
{11,{<0.59.0>,#Ref<0.0.1.167>}},
{12,{<0.60.0>,#Ref<0.0.1.162>}}]}
client: allocate(): Response: {ok,10}
stop(): ansync stop request sent to gen_server
<====== My Gen Frequency Server Shutdown ======>
Reason: normal
Ending Freqs:
{[13,14,15],
[{10,{<0.58.0>,#Ref<0.0.1.172>}},
{11,{<0.59.0>,#Ref<0.0.1.167>}},
{12,{<0.60.0>,#Ref<0.0.1.162>}}]}
client: deallocate(): async deallocate(10) request sent to gen_server
client: deallocate(): async deallocate(11) request sent to gen_server
client: deallocate(): async deallocate(12) request sent to gen_server