Annotation of embedaddon/trafshow/events.c, revision 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>