Skip to content

Instantly share code, notes, and snippets.

@jacoelho
Created April 16, 2017 16:19
Show Gist options
  • Save jacoelho/1ee0e8340b867ff3eab868be42babf07 to your computer and use it in GitHub Desktop.
Save jacoelho/1ee0e8340b867ff3eab868be42babf07 to your computer and use it in GitHub Desktop.
%% 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(frequency).
-export([start/1,allocate/0, allocate/1, deallocate/1,stop/0,show/0]).
-export([init/1]).
-export([test/1, allocate2/1]).
%% These are the start functions used to create and
%% initialize the server.
% Fixed delay during processing
start(Delay) ->
register(frequency,
spawn(frequency, init, [Delay])).
init(Delay) ->
Frequencies = {get_frequencies(), []},
loop(Frequencies, Delay).
% Hard Coded
get_frequencies() -> [10,11,12,13,14,15].
%% The Main Loop
loop(Frequencies, Delay) ->
receive
{request, Pid, allocate} ->
timer:sleep(Delay), % simulate a delay, eg database
{NewFrequencies, Reply} = allocateHelper(Frequencies, Pid),
Pid ! {reply, Reply},
loop(NewFrequencies, Delay);
{request, Pid , {deallocate, Freq}} ->
NewFrequencies = deallocateHelper(Frequencies, Freq),
Pid ! {reply, ok},
loop(NewFrequencies, Delay);
{request, Pid , show} ->
{ _, Used } = Frequencies,
Pid ! {reply, Used},
loop(Frequencies, Delay);
{request, Pid, stop} ->
Pid ! {reply, stopped}
end.
%% Functional interface
allocate() ->
allocate(defaultTimeout()).
% allocate with max wait timeout
allocate(Timeout) ->
clear(), % discard any message in the mailbox so we only see the last message if sucess
frequency ! {request, self(), allocate},
receive
{reply, Reply} -> Reply
after Timeout ->
{error, timeout}
end.
deallocate(Freq) ->
deallocate(Freq, defaultTimeout()).
% deallocate with max wait timeout
deallocate(Freq, Timeout) ->
clear(), % discard any message in the mailbox so we only see the last message if success
frequency ! {request, self(), {deallocate, Freq}},
receive
{reply, Reply} -> Reply
after Timeout ->
{error, timeout}
end.
stop() ->
frequency ! {request, self(), stop},
receive
{reply, Reply} -> Reply
end.
show() ->
frequency ! {request, self(), show},
receive
{reply, Reply} -> Reply
end.
%% The Internal Help Functions used to allocate and
%% deallocate frequencies.
allocateHelper({[], Allocated}, _Pid) ->
{{[], Allocated}, {error, no_frequency}};
allocateHelper({[Freq|Free], Allocated}, Pid) ->
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
deallocateHelper({Free, Allocated}, Freq) ->
NewAllocated=lists:keydelete(Freq, 1, Allocated),
{[Freq|Free], NewAllocated}.
clear() ->
receive
Msg ->
io:format("server cleaning msg ~w from mailbox ~n", [Msg]),
clear()
after 0 ->
ok
end.
defaultTimeout() ->
5000.
% try to allocate in a sequence
% simulate multiple clients
test(Timeout) ->
spawn(frequency, allocate2, [Timeout]),
spawn(frequency, allocate, [Timeout]),
spawn(frequency, allocate, [Timeout]).
% allocate 2 frequencies with same PID
allocate2(Timeout) ->
frequency:allocate(Timeout),
frequency:allocate(Timeout).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment