Skip to content

Instantly share code, notes, and snippets.

@tomekowal
Created April 10, 2017 07:02
Show Gist options
  • Save tomekowal/473c42750ac34845ad1e7fafbd8739b0 to your computer and use it in GitHub Desktop.
Save tomekowal/473c42750ac34845ad1e7fafbd8739b0 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,deallocate/1,stop/0]).
-export([test_non_overloaded_server/0, test_overloaded_server/0]).
-export([init/1]).
%% These are the start functions used to create and
%% initialize the server.
%% Additional WorkTime parameter allows to easily simulate overloaded server,
%% It is passed to init and loop
start(WorkTime) ->
register(frequency,
spawn(frequency, init, [WorkTime])).
init(WorkTime) ->
Frequencies = {get_frequencies(), []},
loop(Frequencies, WorkTime).
% Hard Coded
get_frequencies() -> [10,11,12,13,14,15].
%% The Main Loop
loop(Frequencies, WorkTime) ->
timer:sleep(WorkTime),
receive
{request, Pid, allocate} ->
{NewFrequencies, Reply} = allocate(Frequencies, Pid),
Pid ! {reply, Reply},
loop(NewFrequencies, WorkTime);
{request, Pid , {deallocate, Freq}} ->
NewFrequencies = deallocate(Frequencies, Freq),
Pid ! {reply, ok},
loop(NewFrequencies, WorkTime);
{request, Pid, stop} ->
Pid ! {reply, stopped}
end.
%% Functional interface
allocate() ->
frequency ! {request, self(), allocate},
receive
{reply, Reply} -> Reply
after 10 -> {error, timeout}
end.
deallocate(Freq) ->
frequency ! {request, self(), {deallocate, Freq}},
receive
{reply, Reply} -> Reply
after 10 -> {error, timeout}
end.
stop() ->
frequency ! {request, self(), stop},
receive
{reply, Reply} -> Reply
after 10 -> {error, timeout}
end.
%% The Internal Help Functions used to allocate and
%% deallocate frequencies.
allocate({[], Allocated}, _Pid) ->
{{[], Allocated}, {error, no_frequency}};
allocate({[Freq|Free], Allocated}, Pid) ->
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
deallocate({Free, Allocated}, Freq) ->
NewAllocated=lists:keydelete(Freq, 1, Allocated),
{[Freq|Free], NewAllocated}.
clear() ->
receive
Msg ->
io:format("~p~n", [Msg]),
clear()
after 0 -> ok
end.
%% tests
test_non_overloaded_server() ->
start(0),
{ok, 10} = allocate(),
stop(). % should return stopped
test_overloaded_server() ->
start(100),
{error, timeout} = allocate(),
timer:sleep(100),
clear(), % should print {ok, 10} that came too late
stop(). % should print {error, timeout}, because stop operation also takes too long.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment