Created
July 7, 2020 01:35
-
-
Save tecnowilliam/13fb587f350d5a9eacd86dc4e7433897 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| % Compile: c(frequency_hardened). | |
| -module(frequency_hardened). | |
| -author("William Vargas"). | |
| -version("1.0"). | |
| -export([init/0, start/0, stop/0, allocate/0, deallocate/1, tests/0]). | |
| % Register the server as frequency_hardened | |
| -spec start() -> ?MODULE. | |
| start() -> | |
| register(?MODULE, spawn(?MODULE, init, [])). | |
| % Stop the frequency_hardened server | |
| -spec stop() -> any(). | |
| stop() -> | |
| ?MODULE ! {request, self(), stop}, | |
| io:format("Server stopped~n"), | |
| reply(1000). | |
| % Initialize the server | |
| -spec init() -> any(). | |
| init() -> | |
| process_flag(trap_exit, true), | |
| Frequencies = {get_frequencies(), []}, | |
| io:format("Server started~n"), | |
| loop(Frequencies). | |
| % Get the frequencies | |
| -spec get_frequencies() -> list(integer()). | |
| get_frequencies() -> [10,11,12,13,14,15]. | |
| % Reply/timeout any message | |
| -spec reply(integer()) -> any(). | |
| reply(Timeout) -> | |
| receive | |
| {reply, Reply} -> | |
| io:format("~w~n",[Reply]), | |
| Reply; | |
| _ -> | |
| ok | |
| after Timeout -> | |
| clear(), | |
| {error, timeout} | |
| end. | |
| % Clear all the mailbox | |
| -spec clear() -> ok. | |
| clear() -> | |
| receive | |
| _Msg -> clear() | |
| after 0 -> | |
| io:format("Mailbox cleared~n"), | |
| ok | |
| end. | |
| % Process the server messages | |
| -spec loop(list(integer())) -> any(). | |
| loop(Frequencies) -> | |
| io:format("Frequencies: ~w~n", [Frequencies]), | |
| receive | |
| {request, Pid, allocate} -> | |
| try allocate(Frequencies, Pid) of | |
| {NewFrequencies, Reply} -> | |
| Pid ! {reply, Reply}, | |
| loop(NewFrequencies) | |
| catch | |
| throw:no_frequency -> | |
| Pid ! {reply, {error,no_frequency}}, | |
| loop(Frequencies) | |
| end; | |
| {request, Pid , {deallocate, Freq}} -> | |
| try deallocate(Frequencies, Freq) of | |
| NewFrequencies -> | |
| Pid ! {reply, {deallocate_ok, -Freq}}, | |
| loop(NewFrequencies) | |
| catch | |
| throw:unallocated_frequency -> | |
| Pid ! {reply, {error,unallocated_frequency}}, | |
| loop(Frequencies) | |
| end; | |
| {request, _Pid, overload} -> | |
| timer:sleep(1000), | |
| loop(Frequencies); | |
| {'EXIT', Pid, _Reason} -> | |
| NewFrequencies = exited(Frequencies, Pid), | |
| loop(NewFrequencies); | |
| {request, _Pid, stop} -> | |
| stop() | |
| end. | |
| % Functional interface: allocate | |
| -spec allocate() -> any(). | |
| allocate() -> | |
| ?MODULE ! {request, self(), allocate}, | |
| reply(1000). | |
| % Allocate a frequency | |
| -spec allocate(list(), pid()) -> tuple(). | |
| allocate({[], _Allocated}, _Pid) -> | |
| % {{[], Allocated}, {allocate_error, no_frequency}}; | |
| throw(no_frequency); | |
| allocate({[Freq|Free], Allocated}, Pid) -> | |
| link(Pid), | |
| {{Free, [{Freq, Pid}|Allocated]}, {allocate_ok, Freq}}. | |
| % Functional interface: deallocate | |
| -spec deallocate(integer()) -> any(). | |
| deallocate(Freq) -> | |
| ?MODULE ! {request, self(), {deallocate, Freq}}, | |
| reply(1000). | |
| % Deallocate a frequency | |
| -spec deallocate(tuple(), integer()) -> tuple(). | |
| deallocate({Free, Allocated}, Freq) -> | |
| case lists:keyfind(Freq, 1, Allocated) of | |
| {Freq, Pid} -> | |
| NewAllocated = lists:delete({Freq, Pid}, Allocated), | |
| unlink(Pid), | |
| {[Freq|Free], NewAllocated}; | |
| _ -> | |
| throw(unallocated_frequency) | |
| end. | |
| % Exit from a frequency | |
| -spec exited({list(), list()}, string()) -> tuple(). | |
| exited({Free, Allocated}, Pid) -> | |
| case lists:keysearch(Pid, 2, Allocated) of | |
| {value, {Freq,Pid}} -> | |
| NewAllocated = lists:keydelete(Freq,1,Allocated), | |
| {[Freq|Free],NewAllocated}; | |
| false -> | |
| {Free,Allocated} | |
| end. | |
| % Tests | |
| -spec tests() -> any(). | |
| tests() -> | |
| % Test: Clean mailbox | |
| clear(), | |
| % Test: Start the server | |
| start(), | |
| % Test: Allocate 10,11 and 12 | |
| allocate(), allocate(), allocate(), | |
| % Test: Deallocate 11 | |
| deallocate(11), | |
| % Test: Allocate 11 and 13 | |
| allocate(), allocate(), | |
| % Test: Error - Unallocated frequency | |
| deallocate(15), | |
| % Test: Error - No frequency | |
| allocate(), allocate(), allocate(), | |
| % Test: Overloaded server | |
| io:format("Test overloaded server~n"), | |
| ?MODULE ! {request, self(), overload}, | |
| reply(1000). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment