Skip to content

Instantly share code, notes, and snippets.

@darcros
Created June 30, 2020 18:48
Show Gist options
  • Save darcros/9044c9d72a456a3efe73b02ba64d583a to your computer and use it in GitHub Desktop.
Save darcros/9044c9d72a456a3efe73b02ba64d583a to your computer and use it in GitHub Desktop.
Concurrent Programming in Erlang - The University of Kent - chapter 2.5
-module(frequency_updated).
-export([loop/1, init/1, stop/0, allocate_freq/0, deallocate_freq/1, demo/0, use_freq/0]).
-define(TIMEOUT, 5000).
%% server implementation
allocate({[], Allocated}, _Pid) ->
{{[], Allocated}, {error, no_frequency}};
allocate({[Freq | Free], Allocated}, Pid) ->
case lists:keymember(Pid, 2, Allocated) of
true -> {{[Freq | Free], Allocated}, {error, already_allocated}};
false -> {{Free, [{Freq, Pid} | Allocated]}, {ok, Freq}}
end.
deallocate({Free, Allocated}, {Freq, Pid}) ->
case lists:keyfind(Freq, 1, Allocated) of
{Freq, Pid} ->
NewAllocated = lists:delete({Freq, Pid}, Allocated),
{{[Freq | Free], NewAllocated}, ok};
{Freq, _} ->
{{Free, Allocated}, unauthorized};
false ->
{{Free, Allocated}, not_allocated}
end.
loop(Frequencies) ->
receive
{request, Pid, allocate} ->
{NewFrequencies, Reply} = allocate(Frequencies, Pid),
Pid ! {reply, Reply},
loop(NewFrequencies);
{request, Pid, {deallocate, Freq}} ->
{NewFrequencies, Reply} = deallocate(Frequencies, {Freq, Pid}),
Pid ! {reply, Reply},
loop(NewFrequencies);
{request, Pid, stop} ->
Pid ! {reply, stopped}
end.
%% private functions
clear() ->
receive
_Msg -> clear()
after 0 ->
ok
end.
wait_reply() ->
receive
{reply, Rep} -> Rep
after ?TIMEOUT ->
clear(),
{error, timout}
end.
%% API
init(Frequencies) ->
Server = spawn(frequency_updated, loop, [{Frequencies, []}]),
register(frequency_updated, Server).
stop() ->
frequency_updated ! {request, self(), stop},
wait_reply().
allocate_freq() ->
frequency_updated ! {request, self(), allocate},
wait_reply().
deallocate_freq(Frequency) ->
frequency_updated ! {request, self(), {deallocate, Frequency}},
wait_reply().
%% demo
use_freq() ->
{ok, Freq} = allocate_freq(),
io:format("allocated frequency ~w, releasing in 2 seconds~n", [Freq]),
timer:sleep(2000),
deallocate_freq(Freq),
io:format("released frequency ~w~n", [Freq]).
spawn_client() ->
spawn(frequency_updated, use_freq, []).
demo() ->
init([10, 11, 12]),
spawn_client(),
spawn_client(),
timer:sleep(3000),
stop(),
ok.
@elbrujohalcon
Copy link

Nicely done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment