-
Notifications
You must be signed in to change notification settings - Fork 0
/
stopwatch.erl
89 lines (65 loc) · 2.43 KB
/
stopwatch.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
-module(stopwatch).
-behaviour(gen_server).
%% Server API
-export([start_link/0, stop/0]).
%% Client API
-export([start_timer/0, stop_timer/0, read_timer/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-define(SERVER, stopwatch).
-record(state, {mode = stopped,
start_time = undefined,
stop_time = undefined}).
%%====================================================================
%% Server API
%%====================================================================
start_link() ->
Result = gen_server:start_link({local, ?SERVER}, ?MODULE, [], []),
io:format("Stopwatch server started~n"),
Result.
stop() ->
gen_server:cast(?SERVER, shutdown).
%%====================================================================
%% Client API
%%====================================================================
start_timer() ->
gen_server:cast(?SERVER, start_timer).
stop_timer() ->
gen_server:cast(?SERVER, stop_timer).
read_timer() ->
gen_server:call(?SERVER, read_timer).
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([]) ->
{ok, #state{}}.
handle_cast(shutdown, State) ->
{stop, normal, State};
handle_cast(start_timer, State) ->
StartTime = now(),
io:format("Stopwatch started~n"),
{noreply, State#state{mode = running, start_time = StartTime}};
handle_cast(stop_timer, State) ->
StopTime = now(),
io:format("Stopwatch stopped~n"),
{noreply, State#state{mode = stopped, stop_time = StopTime}}.
handle_call(read_timer, _From, State = #state{mode = running}) ->
Now = now(),
Diff = calc_diff(Now, State#state.start_time),
{reply, Diff, State};
handle_call(read_timer, _From, State = #state{mode = stopped}) ->
Diff = calc_diff(State#state.stop_time, State#state.start_time),
{reply, Diff, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
io:format("Stopwatch server is shutting down~n"),
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%====================================================================
%% Internal functions
%%====================================================================
calc_diff(T2, T1) ->
DiffMicroSecs = timer:now_diff(T2, T1),
round(DiffMicroSecs / 1000).