diff options
author | Trygve Laugstøl <trygvis@inamo.no> | 2024-02-23 07:08:18 +0100 |
---|---|---|
committer | Trygve Laugstøl <trygvis@inamo.no> | 2024-02-23 07:08:18 +0100 |
commit | 5a9cdd3cc89507d4d74f8bded56ce5e037b3b56e (patch) | |
tree | 982ca2e7f9ac4e8c350dfb5c4f60bcfdfff5afaf /learn-you-some-erlang/reminder/src/event.erl | |
parent | 05ae56e5e89abf2993f84e6d52b250131f247c35 (diff) | |
download | erlang-workshop-5a9cdd3cc89507d4d74f8bded56ce5e037b3b56e.tar.gz erlang-workshop-5a9cdd3cc89507d4d74f8bded56ce5e037b3b56e.tar.bz2 erlang-workshop-5a9cdd3cc89507d4d74f8bded56ce5e037b3b56e.tar.xz erlang-workshop-5a9cdd3cc89507d4d74f8bded56ce5e037b3b56e.zip |
wip
Diffstat (limited to 'learn-you-some-erlang/reminder/src/event.erl')
-rw-r--r-- | learn-you-some-erlang/reminder/src/event.erl | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/learn-you-some-erlang/reminder/src/event.erl b/learn-you-some-erlang/reminder/src/event.erl new file mode 100644 index 0000000..58b5b57 --- /dev/null +++ b/learn-you-some-erlang/reminder/src/event.erl @@ -0,0 +1,61 @@ +-module(event). +-export([start/2, start_link/2, cancel/1]). +-export([init/3, loop/1]). +-record(state, {server, + name="", + to_go=0}). + +%%% Public interface +start(EventName, DateTime) -> + spawn(?MODULE, init, [self(), EventName, DateTime]). + +start_link(EventName, DateTime) -> + spawn_link(?MODULE, init, [self(), EventName, DateTime]). + +cancel(Pid) -> + %% Monitor in case the process is already dead + Ref = erlang:monitor(process, Pid), + Pid ! {self(), Ref, cancel}, + receive + {Ref, ok} -> + erlang:demonitor(Ref, [flush]), + ok; + {'DOWN', Ref, process, Pid, _Reason} -> + ok + end. + +%%% Event's innards +init(Server, EventName, DateTime) -> + loop(#state{server=Server, + name=EventName, + to_go=time_to_go(DateTime)}). + +%% Loop uses a list for times in order to go around the ~49 days limit +%% on timeouts. +loop(S = #state{server=Server, to_go=[T|Next]}) -> + receive + {Server, Ref, cancel} -> + Server ! {Ref, ok} + after T*1000 -> + if Next =:= [] -> + Server ! {done, S#state.name}; + Next =/= [] -> + loop(S#state{to_go=Next}) + end + end. + +%%% private functions +time_to_go(TimeOut={{_,_,_}, {_,_,_}}) -> + Now = calendar:local_time(), + ToGo = calendar:datetime_to_gregorian_seconds(TimeOut) - + calendar:datetime_to_gregorian_seconds(Now), + Secs = if ToGo > 0 -> ToGo; + ToGo =< 0 -> 0 + end, + normalize(Secs). + +%% Because Erlang is limited to about 49 days (49*24*60*60*1000) in +%% milliseconds, the following function is used +normalize(N) -> + Limit = 49*24*60*60, + [N rem Limit | lists:duplicate(N div Limit, Limit)]. |