ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/timeout.c
Revision: 1171
Committed: Fri Aug 12 20:00:46 2011 UTC (12 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 4876 byte(s)
Log Message:
- Import ircservices-5.1.24. Don't ever think about modifying anything in this
  folder!
  Since Andrew Church has discontinued his services project in April 2011, the
  ircd-hybrid team has been given permissions to officially continue and
  maintain the already mentioned project.
  The name of this project will be changed for the reason being that the current
  name "IRC Services" is way too generic these days.

  Remember: Don't ever modify anything in here. This folder is kept for reference.

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 */