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
|
|
|
|
|
|
} |