Skip to content

Instantly share code, notes, and snippets.

@tecnowilliam
Created July 14, 2020 22:59
Show Gist options
  • Select an option

  • Save tecnowilliam/32e44fa3479882e98333d4f1eceece77 to your computer and use it in GitHub Desktop.

Select an option

Save tecnowilliam/32e44fa3479882e98333d4f1eceece77 to your computer and use it in GitHub Desktop.
% Compile: c(gs_frequency).
-module(gs_frequency).
-author("William Vargas").
-version("1.0").
-behaviour(gen_server).
% API
-export([start_link/0, get/0, add/1, allocate/0, deallocate/1, reset/0, stop/0]).
% gen_server
-export([init/1, handle_call/3, handle_cast/2]).
% Start the frequency server
-spec start_link() -> pid().
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
% Initialize the server
-spec init(list()) -> {ok,list()}.
init([]) ->
Frequencies = {get_frequencies(), []},
{ok, Frequencies}.
% Get the default frequencies
-spec get_frequencies() -> list().
get_frequencies() ->
[1,2,3,4,5,6,7,8,9,10].
% gen_server:call
-spec get() -> any().
get() ->
gen_server:call(?MODULE, get).
-spec add(integer()) -> any().
add(Freq) ->
gen_server:call(?MODULE, {add, Freq}).
-spec allocate() -> any().
allocate() ->
gen_server:call(?MODULE, allocate).
-spec deallocate(integer()) -> any().
deallocate(Freq) ->
gen_server:call(?MODULE, {deallocate, Freq}).
% gen_server:cast
-spec reset() -> any().
reset() ->
gen_server:cast(?MODULE, reset).
-spec stop() -> any().
stop() ->
gen_server:cast(?MODULE, stop).
% gen_server handle_call
handle_call(get, _From, Freqs) ->
{reply, Freqs, Freqs};
handle_call({add, Freq}, _From, Freqs) ->
{NewFreqs, Reply} = add(Freqs, Freq),
{reply, Reply, NewFreqs};
handle_call(allocate, From, Freqs) ->
{NewFreqs, Reply} = allocate(Freqs, From),
{reply, Reply, NewFreqs};
handle_call({deallocate, Freq}, _From, Freqs) ->
{NewFreqs, Reply} = deallocate(Freqs, Freq),
{reply, Reply, NewFreqs}.
% gen_server handle_cast
handle_cast(reset, _State) ->
{noreply, {get_frequencies(), []}};
handle_cast(stop, _State) ->
gen_server:stop(?MODULE).
% Add a new frequency
-spec add({list(),list()}, integer()) -> {{list(),list()},{atom(), atom()|integer()}}.
add({Free, Allocated}, Freq) ->
case lists:keyfind(Freq, 1, Allocated) of
{Freq, _Pid} ->
{{Free, Allocated}, {error, frequency_exists}};
_ ->
case lists:member(Freq, Free) of
true ->
{{Free, Allocated}, {error, frequency_exists}};
_ ->
{{lists:append(Free,[Freq]), Allocated}, {ok, Freq}}
end
end.
% Allocate a frequency
-spec allocate({list(), list()}, pid()) -> {{list(),list()},{atom(), atom()|integer()}}.
allocate({[], Allocated}, _Pid) ->
{{[], Allocated}, {error, no_frequency}};
allocate({[Freq|Free], Allocated}, Pid) ->
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
% Deallocate a frequency
-spec deallocate({list(), list()}, integer()) -> {{list(),list()},{atom(), atom()|integer()}}.
deallocate({Free, Allocated}, Freq) ->
case lists:keyfind(Freq, 1, Allocated) of
{Freq, Pid} ->
NewAllocated = lists:delete({Freq, Pid}, Allocated),
{{[Freq|Free], NewAllocated}, {ok, Freq}};
_ ->
{{Free, Allocated}, {error, frequency_not_exists}}
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment