| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
static struct pe_watcher_vtbl pe_group_vtbl; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
|
|
|
static pe_watcher *pe_group_allocate(HV *stash, SV *temple) { |
|
4
|
|
|
|
|
|
|
pe_group *ev; |
|
5
|
1
|
|
|
|
|
|
EvNew(12, ev, 1, pe_group); |
|
6
|
1
|
|
|
|
|
|
ev->base.vtbl = &pe_group_vtbl; |
|
7
|
1
|
|
|
|
|
|
PE_RING_INIT(&ev->tm.ring, ev); |
|
8
|
1
|
|
|
|
|
|
ev->tm.at = 0; |
|
9
|
1
|
|
|
|
|
|
ev->timeout = &PL_sv_undef; |
|
10
|
1
|
|
|
|
|
|
ev->members = 3; |
|
11
|
1
|
50
|
|
|
|
|
EvNew(13, ev->member, ev->members, pe_watcher*); |
|
12
|
1
|
50
|
|
|
|
|
Zero(ev->member, ev->members, pe_watcher*); |
|
13
|
1
|
|
|
|
|
|
pe_watcher_init(&ev->base, stash, temple); |
|
14
|
1
|
|
|
|
|
|
WaREPEAT_on(ev); |
|
15
|
1
|
|
|
|
|
|
return (pe_watcher*) ev; |
|
16
|
|
|
|
|
|
|
} |
|
17
|
|
|
|
|
|
|
|
|
18
|
1
|
|
|
|
|
|
static void pe_group_dtor(pe_watcher *ev) { |
|
19
|
|
|
|
|
|
|
int xx; |
|
20
|
1
|
|
|
|
|
|
pe_group *gp = (pe_group*) ev; |
|
21
|
1
|
|
|
|
|
|
SvREFCNT_dec(gp->timeout); |
|
22
|
13
|
100
|
|
|
|
|
for (xx=0; xx < gp->members; xx++) { |
|
23
|
12
|
|
|
|
|
|
pe_watcher *mb = gp->member[xx]; |
|
24
|
12
|
100
|
|
|
|
|
if (mb) |
|
25
|
10
|
|
|
|
|
|
--mb->refcnt; |
|
26
|
|
|
|
|
|
|
} |
|
27
|
1
|
|
|
|
|
|
EvFree(13, gp->member); |
|
28
|
1
|
|
|
|
|
|
pe_watcher_dtor(ev); |
|
29
|
1
|
|
|
|
|
|
EvFree(12, ev); |
|
30
|
1
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
|
|
32
|
1
|
|
|
|
|
|
static char *pe_group_start(pe_watcher *ev, int repeat) { |
|
33
|
1
|
|
|
|
|
|
pe_group *gp = (pe_group*) ev; |
|
34
|
|
|
|
|
|
|
NV timeout; |
|
35
|
|
|
|
|
|
|
|
|
36
|
1
|
50
|
|
|
|
|
if (!ev->callback) |
|
37
|
0
|
|
|
|
|
|
return "without callback"; |
|
38
|
1
|
50
|
|
|
|
|
if (!sv_2interval("group", gp->timeout, &timeout)) |
|
39
|
0
|
|
|
|
|
|
return "repeating group has no timeout"; |
|
40
|
|
|
|
|
|
|
|
|
41
|
1
|
50
|
|
|
|
|
gp->since = WaHARD(ev)? gp->tm.at : NVtime(); |
|
42
|
1
|
|
|
|
|
|
gp->tm.at = timeout + gp->since; |
|
43
|
1
|
|
|
|
|
|
pe_timeable_start(&gp->tm); |
|
44
|
1
|
|
|
|
|
|
return 0; |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
1
|
|
|
|
|
|
static void pe_group_stop(pe_watcher *ev) |
|
48
|
1
|
|
|
|
|
|
{ pe_timeable_stop(&((pe_group*)ev)->tm); } |
|
49
|
|
|
|
|
|
|
|
|
50
|
0
|
|
|
|
|
|
static void pe_group_alarm(pe_watcher *wa, pe_timeable *tm) { |
|
51
|
|
|
|
|
|
|
STRLEN n_a; |
|
52
|
0
|
|
|
|
|
|
pe_group *gp = (pe_group*) wa; |
|
53
|
|
|
|
|
|
|
NV timeout; |
|
54
|
|
|
|
|
|
|
NV remaining; |
|
55
|
0
|
|
|
|
|
|
NV now = NVtime(); |
|
56
|
|
|
|
|
|
|
int xx; |
|
57
|
0
|
0
|
|
|
|
|
for (xx=0; xx < gp->members; xx++) { |
|
58
|
0
|
|
|
|
|
|
pe_watcher *mb = gp->member[xx]; |
|
59
|
0
|
0
|
|
|
|
|
if (!mb) continue; |
|
60
|
0
|
0
|
|
|
|
|
if (gp->since < mb->cbtime) { |
|
61
|
0
|
|
|
|
|
|
gp->since = mb->cbtime; |
|
62
|
|
|
|
|
|
|
} |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
|
|
65
|
0
|
0
|
|
|
|
|
if (!sv_2interval("group", gp->timeout, &timeout)) |
|
66
|
0
|
|
|
|
|
|
croak("Event: can't extract timeout"); /* impossible */ |
|
67
|
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
remaining = gp->since + timeout - now; |
|
69
|
0
|
0
|
|
|
|
|
if (remaining > IntervalEpsilon) { |
|
70
|
0
|
|
|
|
|
|
gp->tm.at = now + remaining; |
|
71
|
0
|
|
|
|
|
|
pe_timeable_start(&gp->tm); |
|
72
|
|
|
|
|
|
|
} else { |
|
73
|
0
|
|
|
|
|
|
pe_event *ev = (*wa->vtbl->new_event)(wa); |
|
74
|
0
|
|
|
|
|
|
++ev->hits; |
|
75
|
0
|
|
|
|
|
|
queueEvent(ev); |
|
76
|
|
|
|
|
|
|
} |
|
77
|
0
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
/* publish C API XXX */ |
|
80
|
11
|
|
|
|
|
|
static void pe_group_add(pe_group *gp, pe_watcher *wa) { |
|
81
|
11
|
|
|
|
|
|
int ok=0; |
|
82
|
|
|
|
|
|
|
int xx; |
|
83
|
11
|
100
|
|
|
|
|
if (gp == (pe_group*) wa) { |
|
84
|
|
|
|
|
|
|
STRLEN n_a; |
|
85
|
1
|
50
|
|
|
|
|
croak("Event: can't add group '%s' to itself", |
|
86
|
2
|
|
|
|
|
|
SvPV(gp->base.desc, n_a)); |
|
87
|
|
|
|
|
|
|
} |
|
88
|
10
|
|
|
|
|
|
++wa->refcnt; |
|
89
|
55
|
100
|
|
|
|
|
for (xx=0; xx < gp->members; xx++) { |
|
90
|
53
|
100
|
|
|
|
|
if (!gp->member[xx]) { |
|
91
|
8
|
|
|
|
|
|
gp->member[xx] = wa; |
|
92
|
8
|
|
|
|
|
|
ok=1; break; |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
} |
|
95
|
10
|
100
|
|
|
|
|
if (!ok) { /* expand array */ |
|
96
|
|
|
|
|
|
|
pe_watcher **ary; |
|
97
|
2
|
50
|
|
|
|
|
EvNew(13, ary, gp->members*2, pe_watcher*); |
|
98
|
2
|
50
|
|
|
|
|
Zero(ary, gp->members*2, pe_watcher*); |
|
99
|
2
|
50
|
|
|
|
|
Copy(gp->member, ary, gp->members, sizeof(pe_watcher*)); |
|
100
|
2
|
|
|
|
|
|
EvFree(13, gp->member); |
|
101
|
2
|
|
|
|
|
|
gp->member = ary; |
|
102
|
2
|
|
|
|
|
|
gp->member[gp->members] = wa; |
|
103
|
2
|
|
|
|
|
|
gp->members *= 2; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
10
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
static void pe_group_del(pe_group *gp, pe_watcher *target) { |
|
108
|
|
|
|
|
|
|
int xx; |
|
109
|
0
|
0
|
|
|
|
|
for (xx=0; xx < gp->members; xx++) { |
|
110
|
0
|
0
|
|
|
|
|
if (gp->member[xx] != target) |
|
111
|
0
|
|
|
|
|
|
continue; |
|
112
|
0
|
|
|
|
|
|
--target->refcnt; |
|
113
|
0
|
|
|
|
|
|
gp->member[xx] = 0; |
|
114
|
0
|
|
|
|
|
|
break; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
0
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
1
|
|
|
|
|
|
WKEYMETH(_group_timeout) { |
|
119
|
1
|
|
|
|
|
|
pe_group *gp = (pe_group*)ev; |
|
120
|
1
|
50
|
|
|
|
|
if (nval) { |
|
121
|
1
|
|
|
|
|
|
SV *old = gp->timeout; |
|
122
|
1
|
|
|
|
|
|
gp->timeout = SvREFCNT_inc(nval); |
|
123
|
1
|
|
|
|
|
|
SvREFCNT_dec(old); |
|
124
|
1
|
|
|
|
|
|
VERIFYINTERVAL("group", gp->timeout); |
|
125
|
|
|
|
|
|
|
/* recalc expiration XXX */ |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
{ |
|
128
|
1
|
|
|
|
|
|
dSP; |
|
129
|
1
|
50
|
|
|
|
|
XPUSHs(gp->timeout); |
|
130
|
1
|
|
|
|
|
|
PUTBACK; |
|
131
|
|
|
|
|
|
|
} |
|
132
|
1
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
|
|
134
|
13
|
|
|
|
|
|
WKEYMETH(_group_add) { |
|
135
|
13
|
|
|
|
|
|
pe_group *gp = (pe_group*)ev; |
|
136
|
13
|
50
|
|
|
|
|
if (!nval) |
|
137
|
0
|
|
|
|
|
|
return; |
|
138
|
13
|
|
|
|
|
|
pe_group_add(gp, sv_2watcher(nval)); |
|
139
|
|
|
|
|
|
|
} |
|
140
|
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
WKEYMETH(_group_del) { |
|
142
|
0
|
|
|
|
|
|
pe_group *gp = (pe_group*)ev; |
|
143
|
0
|
0
|
|
|
|
|
if (!nval) |
|
144
|
0
|
|
|
|
|
|
return; |
|
145
|
0
|
|
|
|
|
|
pe_group_del(gp, sv_2watcher(nval)); |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
24
|
|
|
|
|
|
static void boot_group() { |
|
149
|
24
|
|
|
|
|
|
pe_watcher_vtbl *vt = &pe_group_vtbl; |
|
150
|
24
|
|
|
|
|
|
memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl)); |
|
151
|
24
|
|
|
|
|
|
vt->dtor = pe_group_dtor; |
|
152
|
24
|
|
|
|
|
|
vt->start = pe_group_start; |
|
153
|
24
|
|
|
|
|
|
vt->stop = pe_group_stop; |
|
154
|
24
|
|
|
|
|
|
vt->alarm = pe_group_alarm; |
|
155
|
24
|
|
|
|
|
|
pe_register_vtbl(vt, gv_stashpv("Event::group",1), &event_vtbl); |
|
156
|
24
|
|
|
|
|
|
} |