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
90
91
92
93
94
95
|
%%%-------------------------------------------------------------------
%%% @author Joe Zhao
%%% @copyright (C) 2014, <COMPANY>
%%% @doc
%%% This module serves the purpose of registering and monitoring different events
%%% Whether they are periodic or oneshot.
%%% Events are happening in a sense that none should be depending on those that happend before.
%%% Spawning one with mutable state is thus not recommended and not supported in such modules.
%%% Thus, the events are defined so that none of them would have states change during different invocations.
%%% @end
%%% Created : 27. 四月 2014 19:11
%%%-------------------------------------------------------------------
-module(eventserv).
-author("Joe Zhao").
-include("eventserv.hrl").
-compile([debug_info,export_all]).
%% API
%%-export([]).
event(PPid,S) ->
receive
{_Pid,shutdown} ->
io:format("I, ~p, am killed.\n",[S#event.name])
after S#event.period ->
PPid ! {self(),run,S},
if
%% S#event.spawn -> spawn(S#event.call,[self()]);
true -> (S#event.call)(self())
end,
case S#event.type of
oneshot -> ok;
periodic -> event(PPid,S);
_Else -> ok
end
end.
recloop(Events) ->
receive
{Pid,shutdown} -> [ Proc ! {self(),shutdown} || Proc<- orddict:fetch_keys(Events)];
{PPid,reg,S} ->
Pid = spawn(?MODULE,event,[self(),S]),
link(Pid),
recloop(orddict:store(Pid,S,Events));
{Pid,run,S} ->
io:format("Event run, type ~p: ~p\n",[S#event.type,S#event.name]),
recloop(Events);
{'EXIT',Pid,Cond} when Cond==normal;Cond==shutdown ->
io:format("Event died naturally, pid: ~p\n.",[Pid]),
recloop(orddict:erase(Pid,Events));
{'EXIT',Pid,Cause} ->
S=orddict:fetch(Pid,Events),
io:format("Event died abruptly(~p), pid: ~p ; name: ~p\n.",[Cause,Pid,S#event.name]),
if
S#event.type == periodic ->
io:format("Event(periodic) will restart, name: ~p\n.",[S#event.name]),
self() ! {self(),reg,S}
end,
recloop(orddict:erase(Pid,Events))
end.
evemon(Events) ->
process_flag(trap_exit,true),
register(?MODULE,self()),
recloop(Events).
start() ->
spawn(?MODULE,evemon,[orddict:new()]).
reg_future(Name,Call,T) ->
eventserv ! {self(),reg,#event{name=Name,server=eventserv,
call=Call,period=T,type=oneshot}}.
reg_future(Call,T) ->
eventserv ! {self(),reg,#event{name="Unamed",server=eventserv,
call=Call,period=T,type=oneshot}}.
reg_periodic(Name,Call,T) ->
eventserv ! {self(),reg,#event{name=Name,server=eventserv,
call=Call,period=T}}.
reg_periodic(Call,T) ->
eventserv ! {self(),reg,#event{name="Unamed",server=eventserv,
call=Call,period=T}}.
test() ->
Pid=start(),
Pid ! {self(),reg,#event{name="test1",server=Pid,
call=fun (PPid) -> io:format("HAHA im here!!!!\n") end,period=1000}},
timer:sleep(500),
Pid ! {self(),reg,#event{name="test2",server=Pid,
call=fun (PPid) -> io:format("HAHA im away and buggy!!!!\n"),exit("I just love to die") end,period=1000}},
timer:sleep(10000),
Pid ! {self(),shutdown}.
|