00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: timer.c,v 1.14 2006-10-11 01:54:04 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026 #define TIMEBUFLEN 1024
00027
00028 static egg_timeval_t now;
00029 static char *timestamp_format = NULL;
00030 static char timestamp[TIMEBUFLEN];
00031
00032
00033 static egg_timer_t *timer_list_head = NULL;
00034 static int timer_next_id = 1;
00035
00036 int timer_init()
00037 {
00038 timestamp_format = strdup("[%H:%M] ");
00039 return(0);
00040 }
00041
00042 int timer_shutdown()
00043 {
00044 if (timestamp_format) {
00045 free(timestamp_format);
00046 timestamp_format = NULL;
00047 }
00048 return(0);
00049 }
00050
00051
00052 int timer_get_time(egg_timeval_t *curtime)
00053 {
00054 struct timeval tv;
00055
00056 (void) gettimeofday(&tv, NULL);
00057 curtime->sec = tv.tv_sec;
00058 curtime->usec = tv.tv_usec;
00059 return(0);
00060 }
00061
00062 long timer_update_now(egg_timeval_t *_now)
00063 {
00064 timer_get_time(&now);
00065 if (_now) {
00066 _now->sec = now.sec;
00067 _now->usec = now.usec;
00068 }
00069 return(now.sec);
00070 }
00071
00072 void timer_get_now(egg_timeval_t *_now)
00073 {
00074 _now->sec = now.sec;
00075 _now->usec = now.usec;
00076 }
00077
00078 long timer_get_now_sec(long *sec)
00079 {
00080 if (sec) *sec = now.sec;
00081 return(now.sec);
00082 }
00083
00084
00085 int timer_diff(egg_timeval_t *from_time, egg_timeval_t *to_time, egg_timeval_t *diff)
00086 {
00087 diff->sec = to_time->sec - from_time->sec;
00088 if (diff->sec < 0) {
00089 diff->sec = 0;
00090 diff->usec = 0;
00091 return(1);
00092 }
00093
00094 diff->usec = to_time->usec - from_time->usec;
00095
00096 if (diff->usec < 0) {
00097 if (diff->sec == 0) {
00098 diff->usec = 0;
00099 return(1);
00100 }
00101 diff->sec -= 1;
00102 diff->usec += 1000000;
00103 }
00104
00105 return(0);
00106 }
00107
00108 static int timer_add_to_list(egg_timer_t *timer)
00109 {
00110 egg_timer_t *prev, *ptr;
00111
00112
00113 prev = NULL;
00114 for (ptr = timer_list_head; ptr; ptr = ptr->next) {
00115 if (timer->trigger_time.sec < ptr->trigger_time.sec) break;
00116 if (timer->trigger_time.sec == ptr->trigger_time.sec && timer->trigger_time.usec < ptr->trigger_time.usec) break;
00117 prev = ptr;
00118 }
00119
00120
00121 if (prev) {
00122 timer->next = prev->next;
00123 prev->next = timer;
00124 }
00125 else {
00126 timer->next = timer_list_head;
00127 timer_list_head = timer;
00128 }
00129 return(0);
00130 }
00131
00132 int timer_create_secs(long secs, const char *name, Function callback)
00133 {
00134 egg_timeval_t howlong;
00135
00136 howlong.sec = secs;
00137 howlong.usec = 0;
00138
00139 return timer_create_repeater(&howlong, name, callback);
00140 }
00141
00142 int timer_create_complex(egg_timeval_t *howlong, const char *name, Function callback, void *client_data, int flags, event_owner_t *owner)
00143 {
00144 static int wraparound = 0;
00145 egg_timer_t *timer;
00146
00147
00148 if (timer_next_id < 1) {
00149 timer_next_id = 1;
00150 wraparound = 1;
00151 }
00152 if (wraparound) {
00153 do {
00154 for (timer = timer_list_head; timer; timer = timer->next) {
00155 if (timer->id == timer_next_id) {
00156 timer_next_id++;
00157 if (timer_next_id < 1) timer_next_id = 1;
00158 break;
00159 }
00160 }
00161 } while (timer);
00162 }
00163
00164
00165 timer = malloc(sizeof(*timer));
00166 timer->id = timer_next_id++;
00167 if (name) timer->name = strdup(name);
00168 else timer->name = NULL;
00169 timer->callback = callback;
00170 timer->client_data = client_data;
00171 timer->flags = flags;
00172 timer->howlong.sec = howlong->sec;
00173 timer->howlong.usec = howlong->usec;
00174 timer->trigger_time.sec = now.sec + howlong->sec;
00175 timer->trigger_time.usec = now.usec + howlong->usec;
00176 timer->owner = owner;
00177
00178 timer_add_to_list(timer);
00179
00180 return(timer->id);
00181 }
00182
00183
00184 int timer_destroy(int timer_id)
00185 {
00186 egg_timer_t *prev, *timer;
00187
00188 prev = NULL;
00189 for (timer = timer_list_head; timer; timer = timer->next) {
00190 if (timer->id == timer_id) break;
00191 prev = timer;
00192 }
00193
00194 if (!timer) return(1);
00195
00196
00197 if (prev) prev->next = timer->next;
00198 else timer_list_head = timer->next;
00199
00200 if (timer->owner && timer->owner->on_delete) timer->owner->on_delete(timer->owner, timer->client_data);
00201 if (timer->name) free(timer->name);
00202 free(timer);
00203 return(0);
00204 }
00205
00206 int timer_destroy_all()
00207 {
00208 egg_timer_t *timer, *next;
00209
00210 for (timer = timer_list_head; timer; timer = next) {
00211 next = timer->next;
00212
00213 if (timer->owner && timer->owner->on_delete) timer->owner->on_delete(timer->owner, timer->client_data);
00214 if (timer->name) free(timer->name);
00215 free(timer);
00216 }
00217 timer_list_head = NULL;
00218
00219 return(0);
00220 }
00221
00222 int timer_destroy_by_owner(egg_module_t *module, void *script)
00223 {
00224 int removed = 0;
00225 egg_timer_t *timer, *prev = 0, *next;
00226
00227 for (timer = timer_list_head; timer; timer = next) {
00228 next = timer->next;
00229
00230 if (timer->owner && timer->owner->module == module && (!script || timer->owner->client_data == script)) {
00231 if (prev) prev->next = timer->next;
00232 else timer_list_head = timer->next;
00233 ++removed;
00234
00235 if (timer->owner && timer->owner->on_delete) timer->owner->on_delete(timer->owner, timer->client_data);
00236 if (timer->name) free(timer->name);
00237 free(timer);
00238 } else {
00239 prev = timer;
00240 }
00241 }
00242 return removed;
00243 }
00244
00245 int timer_get_shortest(egg_timeval_t *howlong)
00246 {
00247 egg_timer_t *timer = timer_list_head;
00248
00249
00250 if (!timer) return(1);
00251
00252 timer_diff(&now, &timer->trigger_time, howlong);
00253
00254 return(0);
00255 }
00256
00257 int timer_run()
00258 {
00259 egg_timer_t *timer;
00260 Function callback;
00261 void *client_data;
00262
00263 while (timer_list_head) {
00264 timer = timer_list_head;
00265 if (timer->trigger_time.sec > now.sec || (timer->trigger_time.sec == now.sec && timer->trigger_time.usec > now.usec)) break;
00266
00267 timer_list_head = timer_list_head->next;
00268
00269 callback = timer->callback;
00270 client_data = timer->client_data;
00271
00272 callback(client_data);
00273
00274 if (timer->flags & TIMER_REPEAT) {
00275
00276 timer->trigger_time.sec += timer->howlong.sec;
00277 timer->trigger_time.usec += timer->howlong.usec;
00278 if (timer->trigger_time.usec >= 1000000) {
00279 timer->trigger_time.usec -= 1000000;
00280 timer->trigger_time.sec += 1;
00281 }
00282
00283
00284 timer_add_to_list(timer);
00285 }
00286 else {
00287 if (timer->owner && timer->owner->on_delete) timer->owner->on_delete(timer->owner, timer->client_data);
00288 if (timer->name) free(timer->name);
00289 free(timer);
00290 }
00291
00292 }
00293 return(0);
00294 }
00295
00296 egg_timer_t *timer_list()
00297 {
00298 return(timer_list_head);
00299 }
00300
00301 egg_timer_t *timer_find(int id)
00302 {
00303 egg_timer_t *timer;
00304
00305 for (timer = timer_list_head; timer; timer = timer->next) {
00306 if (timer->id == id) return(timer);
00307 }
00308 return(NULL);
00309 }
00310
00311 int timer_set_timestamp(char *format)
00312 {
00313 str_redup(×tamp_format, format);
00314 return(0);
00315 }
00316
00317 char *timer_get_timestamp(void)
00318 {
00319 time_t now_secs = (time_t)now.sec;
00320 int len;
00321
00322 len = strftime(timestamp, TIMEBUFLEN, timestamp_format, localtime(&now_secs));
00323
00324 if (!len) *timestamp = 0;
00325
00326 return timestamp;
00327 }