ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/timeout.c
Revision: 3389
Committed: Fri Apr 25 14:12:15 2014 UTC (9 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 4876 byte(s)
Log Message:
- Imported ircservices-5.1.24

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 send_timeout_list(User *u)
26 {
27 Timeout *to;
28 uint32 now = time_msec();
29
30 notice(ServerName, u->nick, "Now: %u.%03u", now/1000, now%1000);
31 LIST_FOREACH (to, timeouts) {
32 notice(ServerName, u->nick, "%p: %u.%03u: %p (%p)",
33 to, to->timeout/1000, to->timeout%1000, to->code, to->data);
34 }
35 }
36
37 #endif /* DEBUG_COMMANDS */
38
39 /*************************************************************************/
40
41 /* Check the timeout list for any pending actions. */
42
43 void check_timeouts(void)
44 {
45 Timeout *to, *to2;
46 uint32 now = time_msec();
47
48 if (checking_timeouts)
49 fatal("check_timeouts() called recursively!");
50 checking_timeouts = 1;
51 log_debug(2, "Checking timeouts at time_msec = %u.%03u",
52 now/1000, now%1000);
53
54 LIST_FOREACH_SAFE (to, timeouts, to2) {
55 if (to->timeout) {
56 if ((int32)(to->timeout - now) > 0)
57 continue;
58 log_debug(3, "Running timeout %p (code=%p repeat=%d)",
59 to, to->code, to->repeat);
60 to->code(to);
61 if (to->repeat) {
62 to->timeout = now + to->repeat;
63 if (!to->timeout) /* watch out for zero! */
64 to->timeout++;
65 continue;
66 }
67 }
68 LIST_REMOVE(to, timeouts);
69 free(to);
70 }
71
72 log_debug(2, "Finished timeout list");
73 checking_timeouts = 0;
74 }
75
76 /*************************************************************************/
77
78 /* Add a timeout to the list to be triggered in `delay' seconds. If
79 * `repeat' is nonzero, do not delete the timeout after it is triggered.
80 * This must maintain the property that timeouts added from within a
81 * timeout routine do not get checked during that run of the timeout list.
82 */
83
84 Timeout *add_timeout(int delay, void (*code)(Timeout *), int repeat)
85 {
86 if (delay < 0) {
87 log("add_timeout(): called with a negative delay! (%d)", delay);
88 return NULL;
89 }
90 if (!code) {
91 log("add_timeout(): called with code==NULL!");
92 return NULL;
93 }
94 if (delay > 2147483) { /* 2^31/1000 (watch out for difference overflow) */
95 log("add_timeout(): delay (%ds) too long, shortening to 2147483s",
96 delay);
97 delay = 2147483;
98 }
99 return add_timeout_ms((uint32)delay*1000, code, repeat);
100 }
101
102 /*************************************************************************/
103
104 /* The same thing, but using milliseconds instead of seconds. */
105
106 Timeout *add_timeout_ms(uint32 delay, void (*code)(Timeout *), int repeat)
107 {
108 Timeout *t;
109
110 if (!code) {
111 log("add_timeout_ms(): called with code==NULL!");
112 return NULL;
113 }
114 if (delay > 2147483647) {
115 log("add_timeout_ms(): delay (%dms) too long, shortening to"
116 " 2147483647ms", delay);
117 delay = 2147483647;
118 }
119 t = malloc(sizeof(Timeout));
120 if (!t)
121 return NULL;
122 t->settime = time(NULL);
123 t->timeout = time_msec() + delay;
124 /* t->timeout==0 is used to signal that the timeout should be deleted;
125 * if the timeout value just happens to wrap around to 0, lengthen it
126 * by a millisecond. */
127 if (!t->timeout)
128 t->timeout++;
129 t->code = code;
130 t->data = NULL;
131 t->repeat = repeat ? delay : 0;
132 LIST_INSERT(t, timeouts);
133 return t;
134 }
135
136 /*************************************************************************/
137
138 /* Remove a timeout from the list (if it's there). */
139
140 void del_timeout(Timeout *t)
141 {
142 Timeout *ptr;
143
144 if (!t) {
145 log("del_timeout(): called with t==NULL!");
146 return;
147 }
148 LIST_FOREACH (ptr, timeouts) {
149 if (ptr == t)
150 break;
151 }
152 if (!ptr) {
153 log("del_timeout(): attempted to remove timeout %p (not on list)", t);
154 return;
155 }
156 if (checking_timeouts) {
157 t->timeout = 0; /* delete it when we hit it in the list */
158 return;
159 }
160 LIST_REMOVE(t, timeouts);
161 free(t);
162 }
163
164 /*************************************************************************/
165
166 /*
167 * Local variables:
168 * c-file-style: "stroustrup"
169 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
170 * indent-tabs-mode: nil
171 * End:
172 *
173 * vim: expandtab shiftwidth=4:
174 */