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

# User Rev Content
1 michael 1194 /* 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 michael 1209 void
26 michael 1210 send_timeout_list(User *u)
27 michael 1194 {
28 michael 1209 Timeout *to;
29     uint32 now = time_msec();
30 michael 1194
31 michael 1209 notice(ServerName, u->nick, "Now: %u.%03u", now / 1000, now % 1000);
32 michael 1210
33 michael 1209 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 michael 1194 }
39    
40 michael 1209 #endif /* DEBUG_COMMANDS */
41 michael 1194
42     /*************************************************************************/
43    
44     /* Check the timeout list for any pending actions. */
45    
46 michael 1209 void
47     check_timeouts(void)
48 michael 1194 {
49 michael 1209 Timeout *to, *to2;
50     uint32 now = time_msec();
51 michael 1194
52 michael 1209 if (checking_timeouts)
53     fatal("check_timeouts() called recursively!");
54 michael 1210
55 michael 1209 checking_timeouts = 1;
56 michael 1210
57 michael 1209 log_debug(2, "Checking timeouts at time_msec = %u.%03u",
58     now / 1000, now % 1000);
59 michael 1194
60 michael 1209 LIST_FOREACH_SAFE(to, timeouts, to2)
61     {
62     if (to->timeout)
63     {
64     if ((int32) (to->timeout - now) > 0)
65     continue;
66 michael 1210
67 michael 1209 log_debug(3, "Running timeout %p (code=%p repeat=%d)",
68     to, to->code, to->repeat);
69     to->code(to);
70 michael 1210
71 michael 1209 if (to->repeat)
72     {
73     to->timeout = now + to->repeat;
74 michael 1210
75 michael 1209 if (!to->timeout) /* watch out for zero! */
76     to->timeout++;
77     continue;
78     }
79 michael 1194 }
80 michael 1210
81 michael 1209 LIST_REMOVE(to, timeouts);
82     free(to);
83     }
84 michael 1194
85 michael 1209 log_debug(2, "Finished timeout list");
86     checking_timeouts = 0;
87 michael 1194 }
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 michael 1209 Timeout *
98     add_timeout(int delay, void (*code) (Timeout *), int repeat)
99 michael 1194 {
100 michael 1209 if (delay < 0)
101     {
102     log("add_timeout(): called with a negative delay! (%d)", delay);
103     return NULL;
104     }
105 michael 1210
106 michael 1209 if (!code)
107     {
108     log("add_timeout(): called with code==NULL!");
109     return NULL;
110     }
111 michael 1210
112 michael 1209 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 michael 1210
118 michael 1209 return add_timeout_ms((uint32) delay * 1000, code, repeat);
119 michael 1194 }
120    
121     /*************************************************************************/
122    
123     /* The same thing, but using milliseconds instead of seconds. */
124    
125 michael 1209 Timeout *
126     add_timeout_ms(uint32 delay, void (*code) (Timeout *), int repeat)
127 michael 1194 {
128 michael 1209 Timeout *t;
129 michael 1194
130 michael 1209 if (!code)
131     {
132     log("add_timeout_ms(): called with code==NULL!");
133     return NULL;
134     }
135 michael 1210
136 michael 1209 if (delay > 2147483647)
137     {
138     log("add_timeout_ms(): delay (%dms) too long, shortening to"
139     " 2147483647ms", delay);
140     delay = 2147483647;
141     }
142 michael 1210
143 michael 1209 t = malloc(sizeof(Timeout));
144 michael 1210
145 michael 1209 if (!t)
146     return NULL;
147 michael 1210
148 michael 1209 t->settime = time(NULL);
149     t->timeout = time_msec() + delay;
150 michael 1210
151     /*
152     * t->timeout==0 is used to signal that the timeout should be deleted;
153 michael 1209 * if the timeout value just happens to wrap around to 0, lengthen it
154 michael 1210 * by a millisecond.
155     */
156 michael 1209 if (!t->timeout)
157     t->timeout++;
158 michael 1210
159 michael 1209 t->code = code;
160     t->data = NULL;
161     t->repeat = repeat ? delay : 0;
162     LIST_INSERT(t, timeouts);
163 michael 1210
164 michael 1209 return t;
165 michael 1194 }
166    
167     /*************************************************************************/
168    
169     /* Remove a timeout from the list (if it's there). */
170    
171 michael 1209 void
172 michael 1210 del_timeout(Timeout *t)
173 michael 1194 {
174 michael 1209 Timeout *ptr;
175 michael 1194
176 michael 1209 if (!t)
177     {
178     log("del_timeout(): called with t==NULL!");
179     return;
180     }
181 michael 1210
182 michael 1209 LIST_FOREACH(ptr, timeouts)
183     {
184     if (ptr == t)
185     break;
186     }
187 michael 1210
188 michael 1209 if (!ptr)
189     {
190     log("del_timeout(): attempted to remove timeout %p (not on list)", t);
191     return;
192     }
193 michael 1210
194 michael 1209 if (checking_timeouts)
195     {
196     t->timeout = 0; /* delete it when we hit it in the list */
197     return;
198     }
199 michael 1210
200 michael 1209 LIST_REMOVE(t, timeouts);
201     free(t);
202 michael 1194 }
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     */