Skip to content

Instantly share code, notes, and snippets.

@jonalmeida
Last active April 8, 2017 20:48
Show Gist options
  • Save jonalmeida/27a6b8f65f65ca9ef38375730e119970 to your computer and use it in GitHub Desktop.
Save jonalmeida/27a6b8f65f65ca9ef38375730e119970 to your computer and use it in GitHub Desktop.
Concurrent frequency and ping server
-module(server).
-export([ping/1, init/0]).
% Usage in shell:
%register(server, spawn(server, init, [])).
%server ! {request, self(), allocate}.
%server ! {request, self(), {deallocate, Freq}}.
%register(client, spawn(server, init, [])).
%server ! {ping, client}. % WARNING! This ping-pong server will never end!
ping(Io) ->
receive
{ping, Pid} ->
Io ! io:format("~p sent a ping~n", [self()]),
Pid ! {pong, self()},
timer:sleep(100);
{pong, Pid} ->
Io ! io:format("~p replied with a pong~n", [self()]),
Pid ! {ping, self()},
timer:sleep(100)
end,
ping(Io).
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}.
init() ->
Frequencies = {get_frequencies(), []},
loop(Frequencies).
get_frequencies() -> [10, 14, 15, 17, 20].
loop({_Free, Allocated}=Frequencies) ->
receive
{request, Pid, allocate} ->
IsAllocated = lists:keymember(Pid, 2, Allocated),
case IsAllocated of
true ->
Pid ! {reply, {error, already_allocated}},
loop(Frequencies);
false ->
{NewFrequencies, Reply} = allocate(Frequencies, Pid),
Pid ! {reply, Reply},
loop(NewFrequencies)
end;
{request, Pid, {deallocate, Freq}} ->
case lists:keyfind(Freq, 1, Allocated) of
{Freq, Pid} ->
NewFrequencies = deallocate(Frequencies, Freq),
Pid ! {reply, ok},
loop(NewFrequencies);
false ->
Pid ! {reply, {error, no_matching_freq_pid}},
loop(Frequencies)
end;
{request, Pid, stop} ->
Pid ! {reply, stop}
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment