File Coverage

c/idle.c
Criterion Covered Total %
statement 69 91 75.8
branch 16 36 44.4
condition n/a
subroutine n/a
pod n/a
total 85 127 66.9


line stmt bran cond sub pod time code
1             static struct pe_watcher_vtbl pe_idle_vtbl;
2             static pe_ring Idle;
3              
4             /*#define D_IDLE(x) x /**/
5             #define D_IDLE(x) /**/
6              
7 13           static pe_watcher *pe_idle_allocate(HV *stash, SV *temple) {
8             pe_idle *ev;
9 13           EvNew(3, ev, 1, pe_idle);
10 13           ev->base.vtbl = &pe_idle_vtbl;
11 13           pe_watcher_init(&ev->base, stash, temple);
12 13           PE_RING_INIT(&ev->tm.ring, ev);
13 13           PE_RING_INIT(&ev->iring, ev);
14 13           ev->max_interval = &PL_sv_undef;
15 13           ev->min_interval = newSVnv(.01);
16 13           return (pe_watcher*) ev;
17             }
18              
19 13           static void pe_idle_dtor(pe_watcher *ev) {
20 13           pe_idle *ip = (pe_idle*) ev;
21 13           SvREFCNT_dec(ip->max_interval);
22 13           SvREFCNT_dec(ip->min_interval);
23 13           pe_watcher_dtor(ev);
24 13           EvFree(3, ev);
25 13           }
26              
27 21           static char *pe_idle_start(pe_watcher *ev, int repeating) {
28             NV now;
29             NV min,max;
30 21           pe_idle *ip = (pe_idle*) ev;
31 21 50         if (!ev->callback)
32 0           return "without callback";
33 21 100         if (!repeating) ev->cbtime = NVtime();
34 21 50         now = WaHARD(ev)? ev->cbtime : NVtime();
35 21 50         if (sv_2interval("min", ip->min_interval, &min)) {
36 21           ip->tm.at = min + now;
37 21           pe_timeable_start(&ip->tm);
38             D_IDLE(warn("min %.2f setup '%s'\n", min, SvPV(ev->desc,na)));
39             }
40             else {
41 0           PE_RING_UNSHIFT(&ip->iring, &Idle);
42             D_IDLE(warn("idle '%s'\n", SvPV(ev->desc,na)));
43 0 0         if (sv_2interval("max", ip->max_interval, &max)) {
44             D_IDLE(warn("max %.2f setup '%s'\n", max, SvPV(ev->desc,na)));
45 0           ip->tm.at = max + now;
46 0           pe_timeable_start(&ip->tm);
47             }
48             }
49 21           return 0;
50             }
51              
52 18           static void pe_idle_alarm(pe_watcher *wa, pe_timeable *_ignore) {
53 18           NV now = NVtime();
54             NV min,max,left;
55 18           pe_idle *ip = (pe_idle*) wa;
56 18           pe_timeable_stop(&ip->tm);
57 18 50         if (sv_2interval("min", ip->min_interval, &min)) {
58 18           left = wa->cbtime + min - now;
59 18 100         if (left > IntervalEpsilon) {
60 2           ++TimeoutTooEarly;
61 2           ip->tm.at = now + left;
62 2           pe_timeable_start(&ip->tm);
63             D_IDLE(warn("min %.2f '%s'\n", left, SvPV(wa->desc,na)));
64 2           return;
65             }
66             }
67 16 50         if (PE_RING_EMPTY(&ip->iring)) {
68 16           PE_RING_UNSHIFT(&ip->iring, &Idle);
69             D_IDLE(warn("idle '%s'\n", SvPV(wa->desc,na)));
70             }
71 16 50         if (sv_2interval("max", ip->max_interval, &max)) {
72 0           left = wa->cbtime + max - now;
73 0 0         if (left < IntervalEpsilon) {
74             pe_event *ev;
75             D_IDLE(warn("max '%s'\n", SvPV(wa->desc,na)));
76 0 0         PE_RING_DETACH(&ip->iring);
77 0           ev = (*wa->vtbl->new_event)(wa);
78 0           ++ev->hits;
79 0           queueEvent(ev);
80 0           return;
81             }
82             else {
83 0           ++TimeoutTooEarly;
84 0           ip->tm.at = now + left;
85             D_IDLE(warn("max %.2f '%s'\n", left, SvPV(wa->desc,na)));
86 16           pe_timeable_start(&ip->tm);
87             }
88             }
89             }
90              
91 21           static void pe_idle_stop(pe_watcher *ev) {
92 21           pe_idle *ip = (pe_idle*) ev;
93 21 100         PE_RING_DETACH(&ip->iring);
94 21           pe_timeable_stop(&ip->tm);
95 21           }
96              
97 1           WKEYMETH(_idle_max_interval) {
98 1           pe_idle *ip = (pe_idle*) ev;
99 1 50         if (nval) {
100 0           SV *old = ip->max_interval;
101 0           ip->max_interval = SvREFCNT_inc(nval);
102 0 0         if (old) SvREFCNT_dec(old);
103 0           VERIFYINTERVAL("max", ip->max_interval);
104             }
105             {
106 1           dSP;
107 1 50         XPUSHs(ip->max_interval);
108 1           PUTBACK;
109             }
110 1           }
111              
112 1           WKEYMETH(_idle_min_interval) {
113 1           pe_idle *ip = (pe_idle*) ev;
114 1 50         if (nval) {
115 0           SV *old = ip->min_interval;
116 0           ip->min_interval = SvREFCNT_inc(nval);
117 0 0         if (old) SvREFCNT_dec(old);
118 0           VERIFYINTERVAL("min", ip->min_interval);
119             }
120             {
121 1           dSP;
122 1 50         XPUSHs(ip->min_interval);
123 1           PUTBACK;
124             }
125 1           }
126              
127 24           static void boot_idle() {
128 24           pe_watcher_vtbl *vt = &pe_idle_vtbl;
129 24           PE_RING_INIT(&Idle, 0);
130 24           memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl));
131 24           vt->dtor = pe_idle_dtor;
132 24           vt->start = pe_idle_start;
133 24           vt->stop = pe_idle_stop;
134 24           vt->alarm = pe_idle_alarm;
135 24           pe_register_vtbl(vt, gv_stashpv("Event::idle",1), &event_vtbl);
136 24           }