blob: f65005a644b2f0c9bd92259b5173cde56421c574 (
plain)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include "config.h"
#include <iostream>
#if HAVE_UNISTD_H
#include <unistd.h>
#else
extern "C" long alarm(long);
#endif
#include <signal.h>
#include "alarm.h"
Alarm *Alarm::first=0;
Alarm *Alarm::last=0;
Alarm::~Alarm()
{
Cancel();
}
void Alarm::Unlink()
{
set_interval=0;
if (prev) prev->next=next;
else first=next;
if (next) next->prev=prev;
else last=prev;
}
void Alarm::cancel_sig(unsigned seconds_left)
{
Alarm *p;
Alarm *alarm_chain=0;
while ((p=first) != 0 && p->set_interval <= seconds_left)
// Marginal case
{
p->Unlink();
p->next=alarm_chain;
alarm_chain=p;
}
for (p=first; p; p=p->next)
p->set_interval -= seconds_left;
while ((p=alarm_chain) != 0)
{
alarm_chain=p->next;
p->handler();
}
}
void Alarm::set_sig()
{
if (!first) return;
signal(SIGALRM, &Alarm::alarm_func);
alarm(first->set_interval);
}
RETSIGTYPE Alarm::alarm_func(int)
{
if (first) cancel_sig(first->set_interval);
set_sig();
#if RETSIGTYPE != void
return (0);
#endif
}
unsigned Alarm::sig_left()
{
if (!first) return (0);
unsigned n=alarm(0);
return (n ? n <= first->set_interval ? first->set_interval - n:0:0);
}
void Alarm::Set(unsigned nseconds)
{
Cancel(); // Just in case
if (nseconds == 0)
{
handler(); // Fooey.
return;
}
cancel_sig(sig_left());
Alarm *p;
for (p=first; p; p=p->next)
if (p->set_interval > nseconds)
break;
if (!p)
{
next=0;
if ((prev=last) != 0)
prev->next=this;
else
first=this;
last=this;
}
else
{
if ((prev=p->prev) != 0)
prev->next=this;
else
first=this;
next=p;
p->prev=this;
}
set_interval=nseconds;
set_sig();
}
void Alarm::Cancel()
{
cancel_sig(sig_left());
if (set_interval) Unlink();
set_sig();
}
|