Annotation of embedaddon/trafshow/events.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     Copyright (c) 1999-2003 Rinet Corp., Novosibirsk, Russia
                      3:  *
                      4:  * Redistribution and use in source forms, with and without modification,
                      5:  * are permitted provided that this entire comment appears intact.
                      6:  *
                      7:  * THIS SOURCE CODE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
                      8:  */
                      9: 
                     10: #ifdef HAVE_CONFIG_H
                     11: #include <config.h>
                     12: #endif
                     13: 
                     14: #include <sys/types.h>
                     15: #include <sys/time.h>
                     16: #include <time.h>
                     17: #include <stdlib.h>
                     18: #include <string.h>
                     19: 
                     20: #include "events.h"
                     21: 
                     22: #define        dprintf(x)      /* nope */
                     23: 
                     24: static EVENT *first_event = 0; /* first system event in table */
                     25: 
                     26: /*
                     27:  * Subtract 2 timeval structs: out = out - in. Out result always greater 0.
                     28:  */
                     29: void
                     30: tv_sub(out, in)
                     31:        struct timeval *out;
                     32:        const struct timeval *in;
                     33: {
                     34:        if (out->tv_sec > in->tv_sec) {
                     35:                out->tv_sec -= in->tv_sec;
                     36:                if (out->tv_usec >= in->tv_usec) {
                     37:                        out->tv_usec -= in->tv_usec;
                     38:                } else {
                     39:                        out->tv_sec--;
                     40:                        out->tv_usec += 1000000L - in->tv_usec;
                     41:                }
                     42:        } else if (out->tv_sec == in->tv_sec) {
                     43:                out->tv_sec = 0L;
                     44:                out->tv_usec -= in->tv_usec;
                     45:                if (out->tv_usec < 1)
                     46:                        out->tv_usec = 100L;    /* not zero anyway */
                     47:        } else {
                     48:                out->tv_sec = 0L;
                     49:                out->tv_usec = 100L;    /* not zero anyway */
                     50:        }
                     51: }
                     52: 
                     53: void
                     54: tv_add(out, in)
                     55:        struct timeval *out;
                     56:        const struct timeval *in;
                     57: {
                     58:        out->tv_sec += in->tv_sec;
                     59:        out->tv_usec += in->tv_usec;
                     60:        if (out->tv_usec >= 1000000L) {
                     61:                out->tv_sec++;
                     62:                out->tv_usec -= 1000000L;
                     63:        }
                     64: }
                     65: 
                     66: /*
                     67:  * Round timeval to seconds.
                     68:  */
                     69: u_long
                     70: tv_round(in)
                     71:        const struct timeval *in;
                     72: {
                     73:        u_long sec = in->tv_sec;
                     74:        if (in->tv_usec >= 500000L)
                     75:                sec++;
                     76:        return sec;
                     77: }
                     78: 
                     79: /*
                     80:  * Return time difference in milliseconds.
                     81:  */
                     82: u_long
                     83: tv_diff(tvp1, tvp2)
                     84:        const struct timeval *tvp1, *tvp2;
                     85: {
                     86:        struct timeval diff;
                     87: 
                     88:        if (!timerisset(tvp1) || !timerisset(tvp2))
                     89:                return 0;
                     90: 
                     91:        if (timercmp(tvp1, tvp2, >)) {
                     92:                diff = *tvp1;
                     93:                tv_sub(&diff, tvp2);
                     94:        } else {
                     95:                diff = *tvp2;
                     96:                tv_sub(&diff, tvp1);
                     97:        }
                     98:        return (diff.tv_sec * 1000 + diff.tv_usec / 1000);
                     99: }
                    100: 
                    101: /*
                    102:  * Shift the time to be sharp at (12am + N * period), local time.
                    103:  */
                    104: void
                    105: tv_sharp(tvp, period)
                    106:        struct timeval *tvp;
                    107:        int period;
                    108: {
                    109:        time_t defect;
                    110:        struct tm *tm;
                    111: 
                    112:        if (!tvp) return;
                    113: 
                    114:        tm = localtime((time_t *)&tvp->tv_sec);
                    115:        defect = tm->tm_sec + 60 * tm->tm_min + 3600 * tm->tm_hour;
                    116:        defect %= period;
                    117:        period -= defect;
                    118:        if (period < 1) period = 1;
                    119:        tvp->tv_sec += period;
                    120:        tvp->tv_usec = (long)random() % 1000000L;
                    121: }
                    122: 
                    123: /*
                    124:  * Execute pending event and schedule the next nearest.
                    125:  */
                    126: int
                    127: select_event(tvp)
                    128:        struct timeval *tvp;
                    129: {
                    130:        EVENT *ep, *next_event;
                    131:        struct timeval now, gap, earliest;
                    132: 
                    133:        gettimeofday(&now, 0);
                    134:        gap.tv_sec = 0;
                    135:        gap.tv_usec = 1000L; /* 0.001sec grip */
                    136:        tv_add(&gap, &now);
                    137: again:
                    138:        next_event = 0;
                    139:        timerclear(&earliest);
                    140: 
                    141:        for (ep = first_event; ep; ep = ep->next) {
                    142:                /* skip over the empty slots */
                    143:                if (!ep->func) continue;
                    144: 
                    145:                if (timercmp(&gap, &ep->tv, >)) {
                    146:                        void (*func)() = ep->func;
                    147:                        ep->func = 0;           /* free event slot before */
                    148: 
                    149:                        dprintf(("-call_event(%p/%p)", func, ep->arg));
                    150: 
                    151:                        (*func)(ep->arg);       /* call event function */
                    152:                        goto again;
                    153: 
                    154:                } else if (!timerisset(&earliest) ||
                    155:                           timercmp(&ep->tv, &earliest, <)) {
                    156:                        earliest = ep->tv;
                    157:                        next_event = ep;
                    158:                }
                    159:        }
                    160:        if (!next_event) {      /* no more awaiting events */
                    161: 
                    162:                dprintf(("select_event: no timeout"));
                    163: 
                    164:                return 1;       /* timeout undefined */
                    165:        }
                    166:        if (tvp) {
                    167:                tv_sub(&earliest, &now);
                    168:                *tvp = earliest;
                    169: 
                    170:                dprintf(("=wait_event(%p/%p): timeout=%u.%03d",
                    171:                         next_event->func, next_event->arg,
                    172:                         (unsigned)tvp->tv_sec, (int)(tvp->tv_usec / 1000)));
                    173:        }
                    174:        return 0;       /* timeout defined */
                    175: }
                    176: 
                    177: /*
                    178:  * Add the new system event to be executed at the given time.
                    179:  */
                    180: int
                    181: add_event(tvp, func, arg)
                    182:        struct timeval *tvp;
                    183:        void (*func)(void *);
                    184:        void *arg;
                    185: {
                    186:        EVENT *ep, *prev = 0, *next = 0;
                    187:        struct timeval now, gap;
                    188: 
                    189:        if (!tvp) {
                    190:                gettimeofday(&now, 0);
                    191:                gap.tv_sec = 0;
                    192:                gap.tv_usec = 250000L; /* 0.25sec mean a bit later */
                    193:                tv_add(&gap, &now);
                    194:                tvp = &gap;
                    195:        }
                    196: 
                    197:        /*
                    198:         * The same event in queue may cause a looping! Prevent it.
                    199:         */
                    200:        for (ep = first_event; ep; ep = ep->next) {
                    201:                if (ep->func == func && ep->arg == arg) {
                    202:                        ep->tv = *tvp;
                    203:                        dprintf(("=add_event(%p/%p): modify time", func, arg));
                    204:                        return 0;
                    205:                }
                    206:        }
                    207: 
                    208:        /*
                    209:         * Search for first empty or last event slot.
                    210:         */
                    211:        for (ep = first_event; ep; ep = ep->next) {
                    212:                if (!ep->func) {
                    213:                        next = ep->next;
                    214:                        break;
                    215:                }
                    216:                prev = ep;
                    217:        }
                    218:        if (!ep && (ep = (EVENT *)malloc(sizeof(EVENT))) == 0)
                    219:                return -1;
                    220:        memset(ep, 0, sizeof(EVENT));
                    221:        ep->tv = *tvp;
                    222:        ep->func = func;
                    223:        ep->arg = arg;
                    224:        if (next) ep->next = next;
                    225:        else if (prev) prev->next = ep;
                    226:        if (!first_event) first_event = ep;
                    227: 
                    228: #ifdef notdef
                    229:        {
                    230:                char at_time[50];
                    231:                strftime(at_time, sizeof(at_time), "%T",
                    232:                         localtime((time_t *)&ep->tv.tv_sec));
                    233:                dprintf(("+add_event(%p/%p): schedule=%s.%03d",
                    234:                         func, arg, at_time, (int)(tvp->tv_usec / 1000)));
                    235:        }
                    236: #endif
                    237:        return 0;
                    238: }
                    239: 
                    240: /*
                    241:  * Remove system event from queue if any.
                    242:  */
                    243: int
                    244: remove_event(func, arg)
                    245:        void (*func)(void *);
                    246:        void *arg;
                    247: {
                    248:        int found = 0;
                    249:        EVENT *ep;
                    250: 
                    251:        for (ep = first_event; ep; ep = ep->next) {
                    252:                if ((!func || ep->func == func) && ep->arg == arg) {
                    253:                        ep->func = 0;
                    254:                        found++;
                    255:                }
                    256:        }
                    257:        return found;
                    258: }
                    259: 
                    260: /*
                    261:  * Modify existing system event in queue for the new function argument.
                    262:  */
                    263: int
                    264: change_event(func, arg, new_arg)
                    265:        void (*func)(void *);
                    266:        void *arg, *new_arg;
                    267: {
                    268:        int found = 0;
                    269:        EVENT *ep;
                    270: 
                    271:        for (ep = first_event; ep; ep = ep->next) {
                    272:                if ((!func || ep->func == func) && ep->arg == arg) {
                    273:                        ep->arg = new_arg;
                    274:                        found++;
                    275:                }
                    276:        }
                    277:        return found;
                    278: }
                    279: 
                    280: EVENT *
                    281: find_event(func, arg)
                    282:        void (*func)(void *);
                    283:        void *arg;
                    284: {
                    285:        EVENT *ep;
                    286: 
                    287:        for (ep = first_event; ep; ep = ep->next) {
                    288:                if (ep->func == func && ep->arg == arg)
                    289:                        return ep;
                    290:        }
                    291:        return 0;
                    292: }
                    293: 
                    294: void
                    295: free_events()
                    296: {
                    297:        EVENT *ep, *next;
                    298: 
                    299:        ep = first_event;
                    300:        while (ep) {
                    301:                next = ep->next;
                    302:                free(ep);
                    303:                ep = next;
                    304:        }
                    305:        first_event = 0;
                    306: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>