Skip to content

Instantly share code, notes, and snippets.

@mbateman
Created April 13, 2017 16:04
Show Gist options
  • Save mbateman/556bf89249afb4501f1239d63c32d894 to your computer and use it in GitHub Desktop.
Save mbateman/556bf89249afb4501f1239d63c32d894 to your computer and use it in GitHub Desktop.
Assignment 2
%% Based on code from
%% Erlang Programming
%% Francecso Cesarini and Simon Thompson
%% O'Reilly, 2008
%% http://oreilly.com/catalog/9780596518189/
%% http://www.erlangprogramming.org/
%% (c) Francesco Cesarini and Simon Thompson
-module(supervised_frequency).
-export([allocate/0, deallocate/1, stop_server/0, start_supervisor/0, terminate/0]).
-export([init/1, client/0, init_client/0, init_supervisor/0]).
start_supervisor() ->
register(supervisor, spawn(supervised_frequency, init_supervisor, [])).
init_supervisor() ->
Frequencies = {get_frequencies(), []},
start_server(Frequencies),
process_flag(trap_exit, true),
supervisor_loop(Frequencies).
supervisor_loop(Frequencies) ->
FreqPid = whereis(frequency),
receive
{info, NewFrequencies} ->
supervisor_loop(NewFrequencies);
{'EXIT', FreqPid, _Reason} ->
register(frequency, spawn_link(supervised_frequency, init, [Frequencies])),
supervisor_loop(Frequencies);
_ ->
supervisor_loop(Frequencies)
end.
start_server(Frequencies) ->
register(frequency,
spawn_link(supervised_frequency, init, [Frequencies])).
init(Frequencies) ->
process_flag(trap_exit, true),
loop(Frequencies).
% Hard Coded
get_frequencies() -> [10,11,12,13,14,15].
loop(Frequencies) ->
supervisor ! {info, Frequencies},
SuperPid = whereis(supervisor),
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, terminate} ->
Pid ! {reply, terminate},
exit(terminate);
{request, Pid, stop} ->
Pid ! {reply, stopped};
{'EXIT', SuperPid, _Reason} ->
exit(killed);
{'EXIT', Pid, _Reason} ->
NewFrequencies = exited(Frequencies, Pid),
loop(NewFrequencies)
end.
%% Functional interface
allocate() ->
frequency ! {request, self(), allocate},
receive
{reply, Reply} -> Reply
end.
deallocate(Freq) ->
frequency ! {request, self(), {deallocate, Freq}},
receive
{reply, Reply} -> Reply
end.
stop_server() ->
frequency ! {request, self(), stop},
receive
{reply, Reply} -> Reply
end.
terminate() ->
frequency ! {request, self(), terminate},
receive
{reply, Reply} -> Reply
end.
%% The Internal Help Functions used to allocate and deallocate frequencies.
allocate({[], Allocated}, _Pid) ->
{{[], Allocated}, {error, no_frequency}};
allocate({[Freq|Free], Allocated}, Pid) ->
link(Pid),
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
deallocate({Free, Allocated}, Freq) ->
{value,{Freq,Pid}} = lists:keysearch(Freq,1,Allocated),
unlink(Pid),
NewAllocated=lists:keydelete(Freq, 1, Allocated),
{[Freq|Free], NewAllocated}.
exited({Free, Allocated}, Pid) ->
case lists:keysearch(Pid,2,Allocated) of
{value,{Freq,Pid}} ->
NewAllocated = lists:keydelete(Freq,1,Allocated),
{[Freq|Free],NewAllocated};
false ->
{Free,Allocated}
end.
%% creates a client process
client() ->
spawn(supervised_frequency, init_client, []).
init_client() ->
link(whereis(frequency)),
process_flag(trap_exit, true),
loop_client().
loop_client() ->
receive
{'EXIT', _Pid, _Reason} ->
exit(terminate)
after 0 ->
ok
end,
case whereis(frequency) of
undefined ->
loop_client();
FreqPid ->
FreqPid ! {request, self(), allocate},
receive
{reply, {ok, Freq}} ->
FreqPid ! {request, self(), {deallocate, Freq}},
receive
{reply, _} -> loop_client()
end;
_ ->
loop_client()
after 100 ->
ok
end
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment