File: timer.c

package info (click to toggle)
libevent-perl 1.15-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 792 kB
  • sloc: ansic: 3,034; perl: 1,128; makefile: 2
file content (92 lines) | stat: -rw-r--r-- 2,214 bytes parent folder | download | duplicates (7)
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
static struct pe_watcher_vtbl pe_timer_vtbl;

static pe_watcher *pe_timer_allocate(HV *stash, SV *temple) {
    pe_timer *ev;
    EvNew(7, ev, 1, pe_timer);
    assert(ev);
    ev->base.vtbl = &pe_timer_vtbl;
    PE_RING_INIT(&ev->tm.ring, ev);
    ev->tm.at = 0;
    ev->interval = &PL_sv_undef;
    pe_watcher_init(&ev->base, stash, temple);
    return (pe_watcher*) ev;
}

static void pe_timer_dtor(pe_watcher *ev) {
    pe_timer *tm = (pe_timer*) ev;
    SvREFCNT_dec(tm->interval);
    pe_watcher_dtor(ev);
    EvFree(7, ev);
}

static char *pe_timer_start(pe_watcher *ev, int repeat) {
    STRLEN n_a;
    pe_timer *tm = (pe_timer*) ev;
    if (!ev->callback)
	return "without callback";
    if (repeat) {
	/* We just finished the callback and need to re-insert at
	   the appropriate time increment. */
	NV interval;

	if (!sv_2interval("timer", tm->interval, &interval))
	    return "repeating timer has no interval";

	tm->tm.at = interval + (WaHARD(ev)? tm->tm.at : NVtime());
    }
    if (!tm->tm.at)
	return "timer unset";

    pe_timeable_start(&tm->tm);
    return 0;
}

static void pe_timer_stop(pe_watcher *ev)
{ pe_timeable_stop(&((pe_timer*)ev)->tm); }

static void pe_timer_alarm(pe_watcher *wa, pe_timeable *tm) {
    pe_event *ev = (*wa->vtbl->new_event)(wa);
    ++ev->hits;
    queueEvent(ev);
}

WKEYMETH(_timer_at) {
    pe_timer *tp = (pe_timer*)ev;
    if (nval) {
	int active = WaPOLLING(ev);
	if (active) pe_watcher_off(ev);
	tp->tm.at = SvNV(nval);
	if (active) pe_watcher_on(ev, 0);
    }
    {
	dSP;
	XPUSHs(sv_2mortal(newSVnv(tp->tm.at)));
	PUTBACK;
    }
}

WKEYMETH(_timer_interval) {
    pe_timer *tp = (pe_timer*)ev;
    if (nval) {
	SV *old = tp->interval;
	tp->interval = SvREFCNT_inc(nval);
	SvREFCNT_dec(old);
	VERIFYINTERVAL("timer", tp->interval);
	/* recalc expiration XXX */
    }
    {
	dSP;
	XPUSHs(tp->interval);
	PUTBACK;
    }
}

static void boot_timer() {
    pe_watcher_vtbl *vt = &pe_timer_vtbl;
    memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl));
    vt->dtor = pe_timer_dtor;
    vt->start = pe_timer_start;
    vt->stop = pe_timer_stop;
    vt->alarm = pe_timer_alarm;
    pe_register_vtbl(vt, gv_stashpv("Event::timer",1), &event_vtbl);
}