Annotation of libwww/Library/src/HTTimer.c, revision 2.7

2.1       frystyk     1: /*                                                                  HTEvntrg.c
                      2: **     EVENT MANAGER
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.7     ! eric        6: **     @(#) $Id: HTTimer.c,v 2.6 1996/12/07 19:14:36 frystyk Exp $
2.1       frystyk     7: **
                      8: **     Updated HTEvent module 
                      9: **     This new module combines the functions of the old HTEvent module and 
                     10: **     the HTThread module. We retain the old HTThread module, but it
                     11: **     consists of calls to the HTEvent interfaces
                     12: **
                     13: ** Authors:
                     14: **     EGP     Eric Prud'hommeaux (eric@w3.org)
                     15: ** Bugs
                     16: **
                     17: */
                     18: 
                     19: /* Implementation dependent include files */
                     20: #include "sysdep.h"
                     21: #include "WWWUtil.h"
                     22: #include "WWWCore.h"
                     23: #include "HTReqMan.h"
                     24: #include "HTTimer.h"                                    /* Implemented here */
                     25: 
                     26: struct _HTTimer {
2.2       frystyk    27:     ms_t       millis;         /* Relative value in millis */
                     28:     ms_t       expires;        /* Absolute value in millis */
2.1       frystyk    29:     BOOL       relative;
                     30:     void *     param;          /* Client supplied context */
                     31:     HTTimerCallback * cbf;
                     32: };
                     33: 
2.3       eric       34: PRIVATE HTList * Timers = NULL;                           /* List of timers */
2.1       frystyk    35: 
2.7     ! eric       36: #if 1 /* WATCH_RECURSION */
        !            37: 
        !            38: PRIVATE HTTimer * InTimer = NULL;
        !            39: #define CHECKME(timer) if (InTimer != NULL) HTDebugBreak(); InTimer = timer;
        !            40: #define CLEARME(timer) if (InTimer != timer) HTDebugBreak(); InTimer = NULL;
        !            41: #define SETME(timer) InTimer = timer;
        !            42: 
        !            43: #else /* WATCH_RECURSION */
        !            44: 
        !            45: #define CHECKME(timer)
        !            46: #define CLEARME(timer)
        !            47: #define SETME(timer)
        !            48: 
        !            49: #endif /* !WATCH_RECURSION */
2.1       frystyk    50: /* ------------------------------------------------------------------------- */
                     51: 
2.4       eric       52: #ifdef WWW_WIN_ASYNC
                     53: 
                     54: #define SET_PLATFORM_TIMER(timer)      Timer_setWindowsTimer(timer)
                     55: #define DELETE_PLATFORM_TIMER(timer)   Timer_deleteWindowsTimer(timer)
                     56: 
                     57: PRIVATE int Timer_setWindowsTimer(HTTimer * timer)
                     58: {
                     59:     HWND hwnd;
                     60:     UINT id;
2.5       eric       61:     hwnd = HTEventList_getWinHandle(&id);
2.4       eric       62:     return SetTimer(hwnd, (UINT)timer, (UINT)timer->millis, NULL) != 0;
                     63: }
                     64: 
                     65: PRIVATE int Timer_deleteWindowsTimer(HTTimer * timer)
                     66: {
                     67:     HWND hwnd;
                     68:     UINT id;
2.5       eric       69:     hwnd = HTEventList_getWinHandle(&id);
2.4       eric       70:     return KillTimer(hwnd, (UINT)timer) != 0;
                     71: }
                     72: 
                     73: #else /* WWW_WIN_ASYNC */
                     74: 
                     75: #define SET_PLATFORM_TIMER(timer)
                     76: #define DELETE_PLATFORM_TIMER(timer)
                     77: 
                     78: #endif /* !WWW_WIN_ASYNC */
                     79: 
2.1       frystyk    80: PUBLIC BOOL HTTimer_delete (HTTimer * timer)
                     81: {
2.3       eric       82:     HTList * last;
                     83:     HTList * cur;
2.7     ! eric       84:     CHECKME(timer);
        !            85:     if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
        !            86:        HTDebugBreak();
        !            87:        CLEARME(timer);
2.3       eric       88:        return NO;
2.7     ! eric       89:     }
2.3       eric       90:     HTList_quickRemoveElement(cur, last);
2.4       eric       91:     DELETE_PLATFORM_TIMER(timer);
2.3       eric       92:     if (THD_TRACE) HTTrace("Timer....... Deleted timer %p\n", timer);
2.7     ! eric       93:     CLEARME(timer);
2.3       eric       94:     HT_FREE(timer);
                     95:     return YES;
2.1       frystyk    96: }
                     97: 
                     98: PUBLIC HTTimer * HTTimer_new (HTTimer * timer, HTTimerCallback * cbf,
2.2       frystyk    99:                              void * param, ms_t millis, BOOL relative)
2.1       frystyk   100: {
2.7     ! eric      101:     HTList * last;
        !           102:     HTList * cur;
2.2       frystyk   103:     ms_t now = HTGetTimeInMillis();
2.3       eric      104:     ms_t expires;
2.7     ! eric      105:     HTTimer * pres;
2.3       eric      106: 
2.7     ! eric      107:     CHECKME(timer);
2.3       eric      108:     expires = millis;
                    109:     if (relative) expires += now;
                    110: 
                    111:     if (Timers == NULL)
                    112:        Timers = HTList_new();
                    113: 
                    114:     if (timer) {
                    115: 
                    116:        /*      if a timer is specified, it should already exist
                    117:         */
2.7     ! eric      118:        if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
        !           119:            HTDebugBreak();
        !           120:            CLEARME(timer);
2.3       eric      121:            return NULL;
2.7     ! eric      122:        }
        !           123:        HTList_quickRemoveElement(cur, last);
        !           124:        /* could optimize by sorting from last when ((HTList *)(last->object))->expires < expires (most common case) */
2.3       eric      125:     } else {
                    126: 
                    127:        /*      create a new timer
                    128:         */
2.1       frystyk   129:        if ((timer = (HTTimer *) HT_CALLOC(1, sizeof(HTTimer))) == NULL)
2.2       frystyk   130:            HT_OUTOFMEM("HTTimer_new");
2.7     ! eric      131:        last = Timers;
2.1       frystyk   132:     }
2.7     ! eric      133:     /* sort new element into list
        !           134:      */
        !           135:     for (cur = last; 
        !           136:         (pres = (HTTimer *) HTList_nextObject(cur)) != NULL && pres->expires < expires; 
        !           137:         last = cur);
        !           138:     if (THD_TRACE)
        !           139:        HTTrace("Timer....... Created timer %p with callback %p, context %p, and %s timeout %d\n",
        !           140:                 timer, cbf, param, relative ? "relative" : "absolute", millis);
2.1       frystyk   141:     if (!millis) return timer;
2.3       eric      142:     timer->expires = expires;
2.1       frystyk   143:     timer->cbf = cbf;
                    144:     timer->param = param;
                    145:     timer->millis = millis;
                    146:     timer->relative = relative;
2.7     ! eric      147:     SETME(timer);
2.3       eric      148:     /* may already be obsolete
                    149:      */
2.1       frystyk   150:     if (timer->expires <= now) {
                    151:        int status;
2.7     ! eric      152:        if ((status = (*timer->cbf)(timer, timer->param, HTEvent_TIMEOUT)) != HT_OK) {
2.3       eric      153:            if (cur)
                    154:                HTList_quickRemoveElement(cur, last);
                    155:            HT_FREE(timer);
2.7     ! eric      156:            CLEARME(timer);
2.1       frystyk   157:            return NULL;
                    158:        }
                    159:     }
2.3       eric      160: 
                    161:     /*
                    162:     ** add to list if timer is new
                    163:     */
2.7     ! eric      164:     HTList_addObject(last, (void *)timer);
2.4       eric      165:     SET_PLATFORM_TIMER(timer);
2.7     ! eric      166:     CLEARME(timer);
2.1       frystyk   167:     return timer;
                    168: }
                    169: 
                    170: 
2.7     ! eric      171: PUBLIC BOOL HTTimer_refresh (HTTimer * timer, ms_t now)
        !           172: {
        !           173:     if (timer == NULL || timer->relative == NO)
        !           174:        return NO;
        !           175:     if (HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES) == NULL)
        !           176:        return NO;
        !           177:     return YES;
        !           178: }
        !           179: 
2.1       frystyk   180: PUBLIC BOOL HTTimer_deleteAll (void)
                    181: {
2.3       eric      182:     HTList * cur = Timers;
                    183:     HTTimer * pres;
                    184:     if (Timers) {
                    185:        while ((pres = (HTTimer *) HTList_nextObject(cur))) {
2.4       eric      186:            DELETE_PLATFORM_TIMER(pres);
2.3       eric      187:            HT_FREE(pres);
2.1       frystyk   188:        }
2.3       eric      189:        HTList_delete(Timers);
                    190:        Timers = NULL;
2.1       frystyk   191:        return YES;
                    192:     }
                    193:     return NO;
                    194: }
                    195: 
                    196: /*
                    197: **  When a timer has expired, we dispatch the event handler and re-register the
                    198: **  timer with the next expiration time.
                    199: */
2.3       eric      200: PRIVATE int Timer_dispatch (HTList * cur, HTList * last, int now)
2.1       frystyk   201: {
2.3       eric      202:     HTTimer * timer;
                    203:     int ret;
                    204: 
                    205:     timer = (HTTimer *)HTList_objectOf(cur);
2.7     ! eric      206:     if (timer == NULL) {
        !           207:        HTDebugBreak();
        !           208:        CLEARME(timer);
2.3       eric      209:        return HT_ERROR;
2.7     ! eric      210:     }
2.1       frystyk   211:     if (timer->relative)
                    212:        HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES);
2.3       eric      213:     else
                    214:        HTList_quickRemoveElement(cur, last);
2.1       frystyk   215:     if (THD_TRACE) HTTrace("Timer....... Dispatch timer %p\n", timer);
2.7     ! eric      216: /*    CHECKME(timer); all entries to this function are now re-entry save */
        !           217:     ret = (*timer->cbf) (timer, timer->param, HTEvent_TIMEOUT);
        !           218: /*    CLEARME(timer); */
2.3       eric      219:     if (!timer->relative)
                    220:        HT_FREE(timer);
                    221:     return ret;
                    222: }
                    223: 
                    224: PUBLIC int HTTimer_dispatch (HTTimer * timer)
                    225: {
                    226:     HTList * cur;
                    227:     HTList * last = Timers;
                    228:     ms_t now = HTGetTimeInMillis();
                    229: 
                    230:     cur = HTList_elementOf(Timers, (void *)timer, &last);
                    231:     return Timer_dispatch(cur, last, now);
2.1       frystyk   232: }
                    233: 
2.7     ! eric      234: PUBLIC int HTTimer_next (ms_t * pSoonest)
2.1       frystyk   235: {
2.7     ! eric      236:     HTList * cur;
        !           237:     HTList * last;
        !           238:     HTTimer * pres;
2.3       eric      239:     ms_t now = HTGetTimeInMillis();
2.7     ! eric      240:     int ret = HT_OK;
        !           241:     HTList * head;
2.3       eric      242: 
                    243:     if (Timers == NULL)
2.7     ! eric      244:        return HT_OK;
2.3       eric      245: 
2.7     ! eric      246:     /* The Timers list may be modified during a dispatch
        !           247:     ** so we have to build an intermediate list
        !           248:     */
        !           249:     head = last = HTList_new();
        !           250:     cur = Timers;
2.3       eric      251:     while ((pres = (HTTimer *) HTList_nextObject(cur)) && pres->expires <= now) {
2.7     ! eric      252:        HTList_addObject(last, (void *)pres);
        !           253:        last = HTList_nextObject(last);
        !           254:     }
        !           255: 
        !           256:     /*
        !           257:     ** Now dispatch the intermediate list
        !           258:     */
        !           259:     cur = last = head;
        !           260:     while ((pres = (HTTimer *) HTList_nextObject(cur)) && ret == HT_OK) {
        !           261:        ret = Timer_dispatch(cur, last, now);
2.3       eric      262:        last = cur;
2.2       frystyk   263:     }
2.3       eric      264: 
2.7     ! eric      265:     if (pSoonest) {
        !           266:        /*
        !           267:        **      First element in Timers is the next to expire.
2.3       eric      268:        */
2.7     ! eric      269:        pres = (HTTimer *) HTList_nextObject(Timers);
        !           270:        *pSoonest = pres ? pres->expires - now : 0;
2.1       frystyk   271:     }
2.7     ! eric      272:     HTList_delete(head);
        !           273:     return ret;
2.1       frystyk   274: }

Webmaster