Skip to content

Instantly share code, notes, and snippets.

@tecnowilliam
Created July 11, 2020 00:33
Show Gist options
  • Select an option

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

Select an option

Save tecnowilliam/ee50692d8a715ee8867ef65d78ee36b4 to your computer and use it in GitHub Desktop.
% Compile: c(frequency).
-module(frequency).
-author("William Vargas").
-version("1.0").
-export([init/2, start/2]).
% Register the server as frequency_hardened
-spec start(atom(), list(integer())) -> pid().
start(Process, Frequencies) ->
register(Process, spawn_link(?MODULE, init, [Process, Frequencies])).
% Initialize the server
-spec init(atom(), list(integer())) -> any().
init(Process, Frequencies) ->
process_flag(trap_exit, true),
io:format("~w started: ~w~n", [Process, whereis(Process)]),
loop(Process, Frequencies).
%% The Main Loop
loop(Process, Frequencies) ->
receive
{request, Pid, allocate} ->
{NewFrequencies, Reply} = allocate(Frequencies, Pid),
Pid ! {reply, Reply},
io:format("~w - allocate: ~w~n", [Process, NewFrequencies]),
loop(Process, NewFrequencies);
{request, Pid , {deallocate, Freq}} ->
{NewFrequencies, Reply} = deallocate(Frequencies, Freq),
Pid ! {reply, Reply},
io:format("~w - deallocate ~w: ~w~n", [Process, Freq, NewFrequencies]),
loop(Process, NewFrequencies);
{request, Pid, frequencies} ->
io:format("~w - frequencies: ~w~n", [Process, Frequencies]),
Pid ! {reply, {ok, Frequencies}};
{request, Pid, stop} ->
Pid ! {reply, {ok, stopped}}
end.
% Allocate a frequency
-spec allocate(list(), pid()) -> tuple().
allocate({[], Allocated}, _Pid) ->
{{[], Allocated}, {error, no_frequency}};
allocate({[Freq|Free], Allocated}, Pid) ->
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
% Deallocate a frequency
-spec deallocate(tuple(), integer()) -> tuple().
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, no_frequency}}
end.
% Compile: c(router).
-module(router).
-author("William Vargas").
-version("1.0").
-export([start/0, stop/1, allocate/0, deallocate/1, tests/0]).
% Launch the processes
-spec start() -> any().
start() ->
frequency:start(freq1, {[1,2,3,4,5,6,7,8,9,10],[]}),
frequency:start(freq2, {[11,12,13,14,15,16,17,18,19,20],[]}),
frequency:start(freq3, {[21,22,23,24,25,26,27,28,29,30],[]}).
% Stop a process
-spec stop(atom()) -> any().
stop(Process) ->
Process ! {request, self(), stop},
io:format("~w stopped: ~w~n", [Process, whereis(Process)]).
% Allocate a frequency
-spec allocate() -> any().
allocate() ->
case rand:uniform(3) of
1 -> allocate(freq1);
2 -> allocate(freq2);
_ -> allocate(freq3)
end.
-spec allocate(atom()) -> any().
allocate(Process) ->
case is_pid(whereis(Process)) of
true ->
Process ! {request, self(), allocate},
receive
{reply, Reply} ->
Reply;
_ ->
{error, invalid_reply}
after 1000 ->
clear()
end;
_ ->
allocate()
end.
% Deallocate a frequency
-spec deallocate(integer()) -> any().
deallocate(Freq) ->
case Freq =< 10 of
true ->
deallocate(freq1, Freq);
_ ->
case Freq =< 20 of
true ->
deallocate(freq2, Freq);
_ ->
deallocate(freq3, Freq)
end
end.
deallocate(Process, Freq) ->
Process ! {request, self(), {deallocate, Freq}},
receive
{reply, Reply} ->
Reply;
_ ->
{error, invalid_reply}
after 1000 ->
clear()
end.
% Clear the mailbox
-spec clear() -> ok.
clear() ->
receive
_Msg -> clear()
after 0 ->
io:format("Mailbox cleared~n")
end.
% Tests
% Compile before run the tests
% c(frequency).
% c(router).
-spec tests() -> any().
tests() ->
start(),
allocate(),
allocate(),
allocate(),
allocate(),
allocate(),
deallocate(1),
deallocate(11),
deallocate(21),
stop(freq1),
allocate(),
allocate(),
allocate().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment