Skip to content

Instantly share code, notes, and snippets.

@jason-carter
Last active May 4, 2017 12:33
Show Gist options
  • Save jason-carter/0863db951e56dc6c712c98c7106eb4d6 to your computer and use it in GitHub Desktop.
Save jason-carter/0863db951e56dc6c712c98c7106eb4d6 to your computer and use it in GitHub Desktop.
FutureLearn Concurrent Programming In Erlang 3.11: The frequency server as a gen_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(gf).
-behaviour(gen_server).
% an implementation of this is included.
-export([start_link/0]).
% you need to implement these functions.
-export([init/1, handle_call/3, handle_cast/2]).
% these are implemented for you.
-export([handle_info/2, terminate/2, code_change/3]).
% you will need to implement these.
-export([allocate/0,deallocate/1,stop/0]).
%% These are the start functions used to create and
%% initialize the server.
start_link() ->
gen_server:start_link(
{local, ?MODULE},
?MODULE, [], []).
init([]) ->
Frequencies = {get_frequencies(), []},
{ok, Frequencies}.
% Hard Coded
get_frequencies() -> [10,11,12,13,14,15].
%% Functional interface
allocate() ->
gen_server:call(?MODULE, allocate).
deallocate(Freq) ->
gen_server:cast(?MODULE,{deallocate, Freq}).
stop() ->
gen_server:cast(?MODULE,stop).
handle_call(allocate, From, Frequencies) ->
{NewFrequencies, Reply} = allocate(Frequencies, From),
{reply, Reply, NewFrequencies}.
handle_cast({deallocate, Freq}, Frequencies) ->
NewFrequencies = deallocate(Frequencies, Freq),
{noreply, NewFrequencies};
handle_cast(stop, State) ->
{stop,stop_requested, State}.
%% 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}.
% default implementations
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
C:\Git\FLErlangConcurrency>erl
Eshell V8.2 (abort with ^G)
1> c(gf).
{ok,gf}
2> gf:start_link().
{ok,<0.62.0>}
3> gf:allocate().
{ok,10}
4> gf:deallocate(10).
ok
5> gf:stop().
ok
6> 6>
=ERROR REPORT==== 4-May-2017::13:20:10 ===
** Generic server gf terminating
** Last message in was {'$gen_cast',stop}
** When Server state == {[10,11,12,13,14,15],[]}
** Reason for termination ==
** stop_requested
6> 6> ** exception error: stop_requested
6>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment