Skip to content

Instantly share code, notes, and snippets.

@jason-carter
Created April 25, 2017 15:19
Show Gist options
  • Save jason-carter/59e2a7cd847f8e9add580e6bbb65a9b6 to your computer and use it in GitHub Desktop.
Save jason-carter/59e2a7cd847f8e9add580e6bbb65a9b6 to your computer and use it in GitHub Desktop.
FutureLearn Concurrent Programming In Erlang 2.22: Upgrading the frequency server
%% 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(f6).
-export([start/0,allocate/0,deallocate/1,stop/0]).
-export([init/0,loop/1]).
%% These are the start functions used to create and
%% initialize the server.
start() ->
register(frequency,
spawn(f6, init, [])).
init() ->
Frequencies = {get_frequencies(), []},
loop(Frequencies).
% Hard Coded
get_frequencies() -> [10,11,12,13,14,15].
%% The Main Loop
loop(Frequencies) ->
receive
{request, Pid, allocate} ->
{NewFrequencies, Reply} = allocate(Frequencies, Pid),
Pid ! {reply, Reply},
f6:loop(NewFrequencies);
{request, Pid , {deallocate, Freq}} ->
NewFrequencies = deallocate(Frequencies, Freq),
Pid ! {reply, ok},
f6:loop(NewFrequencies);
{request, Pid, stop} ->
Pid ! {reply, stopped}
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() ->
frequency ! {request, self(), stop},
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) ->
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
deallocate({Free, Allocated}, Freq) ->
NewAllocated=lists:keydelete(Freq, 1, Allocated),
{[Freq|Free], NewAllocated}.
%% 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(f6).
-export([start/0,allocate/0,deallocate/1,stop/0,inject/1]).
-export([init/0,loop/1]).
%% These are the start functions used to create and
%% initialize the server.
start() ->
register(frequency,
spawn(f6, init, [])).
init() ->
Frequencies = {get_frequencies(), []},
loop(Frequencies).
% Hard Coded
get_frequencies() -> [10,11,12,13,14,15].
%% The Main Loop
loop(Frequencies) ->
receive
{request, Pid, allocate} ->
{NewFrequencies, Reply} = allocate(Frequencies, Pid),
Pid ! {reply, Reply},
f6:loop(NewFrequencies);
{request, Pid , {deallocate, Freq}} ->
NewFrequencies = deallocate(Frequencies, Freq),
Pid ! {reply, ok},
f6:loop(NewFrequencies);
{request, Pid, {inject, Freqs}} ->
NewFrequencies = inject(Frequencies, Freqs),
Pid ! {reply, injected},
f6:loop(NewFrequencies);
{request, Pid, stop} ->
Pid ! {reply, stopped}
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.
inject(Freqs) ->
frequency ! {request, self(), {inject, Freqs}},
receive
{reply, Reply} -> Reply
end.
stop() ->
frequency ! {request, self(), stop},
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) ->
{{Free, [{Freq, Pid}|Allocated]}, {ok, Freq}}.
deallocate({Free, Allocated}, Freq) ->
NewAllocated=lists:keydelete(Freq, 1, Allocated),
{[Freq|Free], NewAllocated}.
inject({Free, Allocated}, Freqs) ->
{Free ++ Freqs, Allocated}.
Eshell V8.2 (abort with ^G)
1> cd("f6_original").
C:/Git/FLErlangConcurrency/f6_original
ok
2> c(f6).
{ok,f6}
3> f6:start().
true
4> f6:allocate().
{ok,10}
5> f6:allocate().
{ok,11}
6> f6:allocate().
{ok,12}
7> f6:allocate().
{ok,13}
8> f6:allocate().
{ok,14}
9> f6:allocate().
{ok,15}
10> f6:allocate().
{error,no_frequency}
11> f6:inject([21,22,23]).
** exception error: undefined function f6:inject/1
12> cd("../f6_upgrade").
C:/Git/FLErlangConcurrency/f6_upgrade
ok
13> pwd().
C:/Git/FLErlangConcurrency/f6_upgrade
ok
14> code:load_file(f6).
{module,f6}
15> code:soft_purge(f6).
false
16> f6:allocate().
{error,no_frequency}
17> f6:inject([21,22,23]).
injected
18> f6:allocate().
{ok,21}
19> f6:allocate().
{ok,22}
20> f6:allocate().
{ok,23}
21> f6:allocate().
{error,no_frequency}
22> f6:stop().
stopped
23>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment