File: timeable.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 (107 lines) | stat: -rw-r--r-- 2,748 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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
static pe_timeable Timeables;

/*#define D_TIMEABLE(x) x /**/
#define D_TIMEABLE(x) /**/

static void db_show_timeables()
{
  pe_timeable *tm = (pe_timeable*) Timeables.ring.next;
  warn("timeables at %.2f\n", NVtime() + IntervalEpsilon);
  while (tm->ring.self) {
    STRLEN n_a;
    pe_watcher *wa = (pe_watcher*) tm->ring.self;
    pe_timeable *next = (pe_timeable*) tm->ring.next;
    warn("  %.2f '%s'\n", tm->at, SvPV(wa->desc, n_a));
    tm = next;
  }
}

static void pe_timeables_check() {
    pe_timeable *tm = (pe_timeable*) Timeables.ring.next;
    NV now = NVtime() + IntervalEpsilon;
    /*db_show_timeables();/**/
    while (tm->ring.self && now >= tm->at) {
	pe_watcher *ev = (pe_watcher*) tm->ring.self;
	pe_timeable *next = (pe_timeable*) tm->ring.next;
	D_TIMEABLE({
	    if (WaDEBUGx(ev) >= 4) {
		STRLEN n_a;
		warn("Event: timeable expire '%s'\n", SvPV(ev->desc, n_a));
	    }
	})
	    assert(!WaSUSPEND(ev));
	assert(WaACTIVE(ev));
	PE_RING_DETACH(&tm->ring);
	(*ev->vtbl->alarm)(ev, tm);
	tm = next;
    }
}

static NV timeTillTimer() {
    pe_timeable *tm = (pe_timeable*) Timeables.ring.next;
    if (!tm->ring.self)
	return 3600;
    return tm->at - NVtime();
}

static void pe_timeable_start(pe_timeable *tm) {
    /* OPTIMIZE! */
    pe_watcher *ev = (pe_watcher*) tm->ring.self;
    pe_timeable *rg = (pe_timeable*) Timeables.ring.next;
    assert(!WaSUSPEND(ev));
    assert(PE_RING_EMPTY(&tm->ring));
    if (WaDEBUGx(ev)) {
	NV left = tm->at - NVtime();
	if (left < 0) {
	    STRLEN n_a;
	    warn("Event: timer for '%s' set to expire immediately (%.2f)",
		 SvPV(ev->desc, n_a), left);
	}
    }
    while (rg->ring.self && rg->at < tm->at) {
	rg = (pe_timeable*) rg->ring.next;
    }
    /*warn("-- adding 0x%x:\n", ev); db_show_timeables();/**/
    PE_RING_ADD_BEFORE(&tm->ring, &rg->ring);
    /*warn("T:\n"); db_show_timeables();/**/
    D_TIMEABLE({
	if (WaDEBUGx(ev) >= 4) {
	    STRLEN n_a;
	    warn("Event: timeable start '%s'\n", SvPV(ev->desc, n_a));
	}
    })
}

static void pe_timeable_stop(pe_timeable *tm) {
    D_TIMEABLE({
	pe_watcher *ev = (pe_watcher*) tm->ring.self;
	if (WaDEBUGx(ev) >= 4) {
	    STRLEN n_a;
	    warn("Event: timeable stop '%s'\n", SvPV(ev->desc, n_a));
	}
    })
    PE_RING_DETACH(&tm->ring);
}

static void pe_timeable_adjust(NV delta) {
    pe_timeable *rg = (pe_timeable*) Timeables.ring.next;
    while (rg != &Timeables) {
	rg->at += delta;
	rg = (pe_timeable*) rg->ring.next;
    }
}

WKEYMETH(_timeable_hard) { /* applies to all timers in a watcher; is ok? */
    if (nval) {
	if (sv_true(nval)) WaHARD_on(ev); else WaHARD_off(ev);
    }
    {
	dSP;
	XPUSHs(boolSV(WaHARD(ev)));
	PUTBACK;
    }
}

static void boot_timeable() {
    PE_RING_INIT(&Timeables.ring, 0);
}