ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hybrid-ircservices-1/timeout.c
Revision: 1210
Committed: Thu Aug 25 19:39:01 2011 UTC (14 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 4690 byte(s)
Log Message:
- style corrections

File Contents

# Content
1 /* Routines for time-delayed actions.
2 *
3 * IRC Services is copyright (c) 1996-2009 Andrew Church.
4 * E-mail: <achurch@achurch.org>
5 * Parts written by Andrew Kempe and others.
6 * This program is free but copyrighted software; see the file GPL.txt for
7 * details.
8 */
9
10 #include "services.h"
11 #define IN_TIMEOUT_C
12 #include "timeout.h"
13
14 /*************************************************************************/
15
16 static Timeout *timeouts = NULL;
17 static int checking_timeouts = 0;
18
19 /*************************************************************************/
20
21 #ifdef DEBUG_COMMANDS
22
23 /* Send the timeout list to the given user. */
24
25 void
26 send_timeout_list(User *u)
27 {
28 Timeout *to;
29 uint32 now = time_msec();
30
31 notice(ServerName, u->nick, "Now: %u.%03u", now / 1000, now % 1000);
32
33 LIST_FOREACH(to, timeouts)
34 {
35 notice(ServerName, u->nick, "%p: %u.%03u: %p (%p)",
36 to, to->timeout / 1000, to->timeout % 1000, to->code, to->data);
37 }
38 }
39
40 #endif /* DEBUG_COMMANDS */
41
42 /*************************************************************************/
43
44 /* Check the timeout list for any pending actions. */
45
46 void
47 check_timeouts(void)
48 {
49 Timeout *to, *to2;
50 uint32 now = time_msec();
51
52 if (checking_timeouts)
53 fatal("check_timeouts() called recursively!");
54
55 checking_timeouts = 1;
56
57 log_debug(2, "Checking timeouts at time_msec = %u.%03u",
58 now / 1000, now % 1000);
59
60 LIST_FOREACH_SAFE(to, timeouts, to2)
61 {
62 if (to->timeout)
63 {
64 if ((int32) (to->timeout - now) > 0)
65 continue;
66
67 log_debug(3, "Running timeout %p (code=%p repeat=%d)",
68 to, to->code, to->repeat);
69 to->code(to);
70
71 if (to->repeat)
72 {
73 to->timeout = now + to->repeat;
74
75 if (!to->timeout) /* watch out for zero! */
76 to->timeout++;
77 continue;
78 }
79 }
80
81 LIST_REMOVE(to, timeouts);
82 free(to);
83 }
84
85 log_debug(2, "Finished timeout list");
86 checking_timeouts = 0;
87 }
88
89 /*************************************************************************/
90
91 /* Add a timeout to the list to be triggered in `delay' seconds. If
92 * `repeat' is nonzero, do not delete the timeout after it is triggered.
93 * This must maintain the property that timeouts added from within a
94 * timeout routine do not get checked during that run of the timeout list.
95 */
96
97 Timeout *
98 add_timeout(int delay, void (*code) (Timeout *), int repeat)
99 {
100 if (delay < 0)
101 {
102 log("add_timeout(): called with a negative delay! (%d)", delay);
103 return NULL;
104 }
105
106 if (!code)
107 {
108 log("add_timeout(): called with code==NULL!");
109 return NULL;
110 }
111
112 if (delay > 2147483)
113 { /* 2^31/1000 (watch out for difference overflow) */
114 log("add_timeout(): delay (%ds) too long, shortening to 2147483s", delay);
115 delay = 2147483;
116 }
117
118 return add_timeout_ms((uint32) delay * 1000, code, repeat);
119 }
120
121 /*************************************************************************/
122
123 /* The same thing, but using milliseconds instead of seconds. */
124
125 Timeout *
126 add_timeout_ms(uint32 delay, void (*code) (Timeout *), int repeat)
127 {
128 Timeout *t;
129
130 if (!code)
131 {
132 log("add_timeout_ms(): called with code==NULL!");
133 return NULL;
134 }
135
136 if (delay > 2147483647)
137 {
138 log("add_timeout_ms(): delay (%dms) too long, shortening to"
139 " 2147483647ms", delay);
140 delay = 2147483647;
141 }
142
143 t = malloc(sizeof(Timeout));
144
145 if (!t)
146 return NULL;
147
148 t->settime = time(NULL);
149 t->timeout = time_msec() + delay;
150
151 /*
152 * t->timeout==0 is used to signal that the timeout should be deleted;
153 * if the timeout value just happens to wrap around to 0, lengthen it
154 * by a millisecond.
155 */
156 if (!t->timeout)
157 t->timeout++;
158
159 t->code = code;
160 t->data = NULL;
161 t->repeat = repeat ? delay : 0;
162 LIST_INSERT(t, timeouts);
163
164 return t;
165 }
166
167 /*************************************************************************/
168
169 /* Remove a timeout from the list (if it's there). */
170
171 void
172 del_timeout(Timeout *t)
173 {
174 Timeout *ptr;
175
176 if (!t)
177 {
178 log("del_timeout(): called with t==NULL!");
179 return;
180 }
181
182 LIST_FOREACH(ptr, timeouts)
183 {
184 if (ptr == t)
185 break;
186 }
187
188 if (!ptr)
189 {
190 log("del_timeout(): attempted to remove timeout %p (not on list)", t);
191 return;
192 }
193
194 if (checking_timeouts)
195 {
196 t->timeout = 0; /* delete it when we hit it in the list */
197 return;
198 }
199
200 LIST_REMOVE(t, timeouts);
201 free(t);
202 }
203
204 /*************************************************************************/
205
206 /*
207 * Local variables:
208 * c-file-style: "stroustrup"
209 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
210 * indent-tabs-mode: nil
211 * End:
212 *
213 * vim: expandtab shiftwidth=4:
214 */