-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenserver.erl
77 lines (69 loc) · 1.74 KB
/
genserver.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
-module(genserver).
-export([start/3, request/2, request/3, requestAsync/2, update/2, timeSince/1, maybeWait/0]).
%% Spawn a process and register it with a given atom
%% Function F should have arity 1
start(Atom, State, F) ->
Pid = spawn(fun() -> loop(State, F) end),
catch(unregister(Atom)),
register(Atom, Pid),
Pid.
loop(State, F) ->
receive
{request, From, Ref, Data} ->
case catch(F(State, Data)) of
{'EXIT', Reason} ->
From!{exit, Ref, Reason},
loop(State, F);
{R, NewState} ->
From!{result, Ref, R},
loop(NewState, F)
end;
{update, From, Ref, NewF} ->
From ! {ok, Ref},
loop(State, NewF);
stop ->
true
end.
%% Send a request to a Pid and wait for a response
request(Pid, Data) ->
request(Pid, Data, 3000).
%% Send a request to a Pid and wait for a response
%% With a specified timeout
request(Pid, Data, Timeout) ->
Ref = make_ref(),
Pid!{request, self(), Ref, Data},
receive
{result, Ref, Result} ->
Result;
{exit, Ref, Reason} ->
exit(Reason)
after Timeout ->
exit("Timeout")
end.
%% Send a request to a Pid without waiting
requestAsync(Pid, Data) ->
Ref = make_ref(),
Pid!{request, self(), Ref, Data}.
update(Pid, Fun) ->
Ref = make_ref(),
Pid!{update, self(), Ref, Fun},
receive
{ok, Ref} ->
ok
end.
%% Returns time since TimeStamp in milliseconds (ms)
timeSince(TimeStamp) ->
timer:now_diff(now(), TimeStamp) / 1000.
%% If process sleepy exists, ask her if we should sleep
maybeWait() ->
case whereis(sleepy) of
undefined -> ok ;
Pid ->
Pid ! {hi, self()},
receive
{wait, N} -> timer:sleep(N) ;
{go} -> ok
after 100 ->
ok
end
end.