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/dev_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/dev_event.erl')
-rw-r--r-- | learn-you-some-erlang/reminder/src/dev_event.erl | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/learn-you-some-erlang/reminder/src/dev_event.erl b/learn-you-some-erlang/reminder/src/dev_event.erl new file mode 100644 index 0000000..5b752ac --- /dev/null +++ b/learn-you-some-erlang/reminder/src/dev_event.erl @@ -0,0 +1,82 @@ +%%% This module is there to test the incomplete loops and constructs +%%% that are presented in the text, but are not the final result. +-module(dev_event). +-compile(export_all). +-record(state, {server, + name="", + to_go=0}). + +start1(EventName, Delay) -> + spawn(?MODULE, init1, [self(), EventName, Delay]). + +start_link1(EventName, Delay) -> + spawn_link(?MODULE, init1, [self(), EventName, Delay]). + +start2(EventName, Delay) -> + spawn(?MODULE, init2, [self(), EventName, Delay]). + +start_link2(EventName, Delay) -> + spawn_link(?MODULE, init2, [self(), EventName, Delay]). + +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 +init1(Server, EventName, Delay) -> + loop2(#state{server=Server, + name=EventName, + to_go=normalize(Delay)}). + +init2(Server, EventName, DateTime) -> + loop2(#state{server=Server, + name=EventName, + to_go=time_to_go(DateTime)}). + +loop1(S = #state{server=Server}) -> + receive + {Server, Ref, cancel} -> + Server ! {Ref, ok} + after S#state.to_go * 1000 -> + Server ! {done, S#state.name} + end. + +%% Loop uses a list for times in order to go around the ~49 days limit +%% on timeouts. +loop2(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 =/= [] -> + loop2(S#state{to_go=Next}) + end + end. + + +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)]. |