Skip to content

Instantly share code, notes, and snippets.

@Xdeon
Created July 7, 2020 05:32
Show Gist options
  • Save Xdeon/948a73c8e899184460fa6e5e39282178 to your computer and use it in GitHub Desktop.
Save Xdeon/948a73c8e899184460fa6e5e39282178 to your computer and use it in GitHub Desktop.
-module(frequency).
-export([start/0, init/0]).
start() ->
Pid = spawn(?MODULE, init, []),
register(?MODULE, Pid),
Pid.
init() ->
Frequencies = {get_frequencies(), []},
loop(Frequencies).
get_frequencies() ->
[10, 11, 12, 13, 14, 15].
loop(Frequencies) ->
receive
{request, Pid, allocate} ->
{NewFrequencies, Reply} = allocate(Frequencies, Pid),
Pid ! {reply, Reply},
loop(NewFrequencies);
{request, Pid, {deallocate, Freq}} ->
NewFrequencies = deallocate(Frequencies, Freq),
Pid ! {reply, ok},
loop(NewFrequencies);
{request, Pid, stop} ->
Pid ! {reply, stopped}
end.
allocate({Freqs, Allocated}, Pid) ->
case lists:keymember(Pid, 2, Allocated) of
true -> {{Freqs, Allocated}, {error, already_allocated}};
false -> do_allocate({Freqs, Allocated}, Pid)
end.
do_allocate({[], Allocated}, _Pid) ->
{{[], Allocated}, {error, no_frequency}};
do_allocate({[Freq|Free], Allocated}, Pid) ->
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
deallocate({Free, Allocated}, Freq) ->
case lists:keymember(Freq, 1, Allocated) of
true ->
{[Freq|Free], lists:keydelete(Freq, 1, Allocated)};
false ->
{Free, Allocated}
end.
% tests
-include_lib("eunit/include/eunit.hrl").
client_recv() ->
receive
{reply, Reply} -> Reply
end.
frequency_test() ->
Freq = start(),
% test naming
?assertEqual(Freq, whereis(?MODULE)),
% test allocate
?MODULE ! {request, self(), allocate},
?assertEqual({ok, 10}, client_recv()),
% test duplicate allocate
?MODULE ! {request, self(), allocate},
?assertEqual({error, already_allocated}, client_recv()),
% test inproper deallocate
?MODULE ! {request, self(), {deallocate, 11}},
?assertEqual(ok, client_recv()),
?MODULE ! {request, self(), allocate},
?assertEqual({error, already_allocated}, client_recv()),
% test proper deallocate
?MODULE ! {request, self(), {deallocate, 10}},
?assertEqual(ok, client_recv()),
?MODULE ! {request, self(), allocate},
?assertEqual({ok, 10}, client_recv()),
% test stop
?MODULE ! {request, self(), stop},
?assertEqual(stopped, client_recv()),
ok.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment