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

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.23    ! frystyk     6: **     @(#) $Id: HTTimer.c,v 2.22 1998/05/31 18:55:48 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 */
2.20      frystyk    20: #include "wwwsys.h"
2.1       frystyk    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;
2.21      frystyk    30:     BOOL       repetitive;
2.1       frystyk    31:     void *     param;          /* Client supplied context */
                     32:     HTTimerCallback * cbf;
                     33: };
                     34: 
2.3       eric       35: PRIVATE HTList * Timers = NULL;                           /* List of timers */
2.1       frystyk    36: 
2.9       frystyk    37: PRIVATE HTTimerSetCallback * SetPlatformTimer = NULL;
                     38: PRIVATE HTTimerSetCallback * DeletePlatformTimer = NULL;
                     39: 
2.17      frystyk    40: #if 0 /* WATCH_RECURSION */
2.7       eric       41: 
                     42: PRIVATE HTTimer * InTimer = NULL;
2.19      frystyk    43: #define CHECKME(timer) if (InTimer != NULL) HTDebugBreak(__FILE__, __LINE__, "\n"); InTimer = timer;
                     44: #define CLEARME(timer) if (InTimer != timer) HTDebugBreak(__FILE, __LINE__, "\n"); InTimer = NULL;
2.7       eric       45: #define SETME(timer) InTimer = timer;
                     46: 
                     47: #else /* WATCH_RECURSION */
                     48: 
                     49: #define CHECKME(timer)
                     50: #define CLEARME(timer)
                     51: #define SETME(timer)
                     52: 
                     53: #endif /* !WATCH_RECURSION */
2.1       frystyk    54: /* ------------------------------------------------------------------------- */
                     55: 
2.23    ! frystyk    56: /*
        !            57: **  When a timer has expired, we dispatch the event handler and re-register the
        !            58: **  timer with the next expiration time if repetitive. Otherwise we just leave
        !            59: **  it
        !            60: */
        !            61: PRIVATE int Timer_dispatch (HTList * cur, HTList * last)
        !            62: {
        !            63:     HTTimer * timer;
        !            64:     int ret = HT_ERROR;
        !            65: 
        !            66:     timer = (HTTimer *)HTList_objectOf(cur);
        !            67:     if (timer == NULL) {
        !            68: #if 0
        !            69:         HTDebugBreak(__FILE__, __LINE__, "Timer dispatch couldn't find a timer\n");
        !            70: #endif
        !            71:         CLEARME(timer);
        !            72:        return HT_ERROR;
        !            73:     }
        !            74:     if (timer->repetitive)
        !            75:        HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES, YES);
        !            76:     else
        !            77:        HTList_quickRemoveElement(cur, last);
        !            78:     if (THD_TRACE) HTTrace("Timer....... Dispatch timer %p\n", timer);
        !            79:     ret = (*timer->cbf) (timer, timer->param, HTEvent_TIMEOUT);
        !            80:     return ret;
        !            81: }
        !            82: 
2.9       frystyk    83: PUBLIC BOOL HTTimer_registerSetTimerCallback (HTTimerSetCallback * cbf)
2.4       eric       84: {
2.9       frystyk    85:     if (CORE_TRACE) HTTrace("Timer....... registering %p as timer set cbf\n", cbf);
                     86:     if (cbf) {
                     87:        SetPlatformTimer = cbf;
                     88:        return YES;
                     89:     }
                     90:     return NO;
2.4       eric       91: }
                     92: 
2.9       frystyk    93: PUBLIC BOOL HTTimer_registerDeleteTimerCallback (HTTimerSetCallback * cbf)
2.4       eric       94: {
2.9       frystyk    95:     if (CORE_TRACE) HTTrace("Timer....... registering %p as timer delete cbf\n", cbf);
                     96:     if (cbf) {
                     97:        DeletePlatformTimer = cbf;
                     98:        return YES;
                     99:     }
                    100:     return NO;
2.10      eric      101: }
                    102: 
                    103: PUBLIC ms_t HTTimer_getTime(HTTimer * timer)
                    104: {
                    105:     if (timer)
                    106:        return timer->millis;
                    107:     return 0;
2.4       eric      108: }
                    109: 
2.1       frystyk   110: PUBLIC BOOL HTTimer_delete (HTTimer * timer)
                    111: {
2.3       eric      112:     HTList * last;
                    113:     HTList * cur;
2.7       eric      114:     CHECKME(timer);
2.23    ! frystyk   115:     if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) CLEARME(timer);
2.18      frystyk   116:     if (HTList_quickRemoveElement(cur, last)) {
2.23    ! frystyk   117:        if (THD_TRACE) HTTrace("Timer....... Deleted active timer %p\n", timer);
2.18      frystyk   118:     } else { 
2.23    ! frystyk   119:        if (THD_TRACE) HTTrace("Timer....... Deleted expired timer %p\n", timer);
2.18      frystyk   120:     }
2.9       frystyk   121: 
                    122:     /*
                    123:     **  Call any platform specific timer handler
                    124:     */
                    125:     if (DeletePlatformTimer) DeletePlatformTimer(timer);
                    126: 
2.7       eric      127:     CLEARME(timer);
2.3       eric      128:     HT_FREE(timer);
                    129:     return YES;
2.1       frystyk   130: }
                    131: 
                    132: PUBLIC HTTimer * HTTimer_new (HTTimer * timer, HTTimerCallback * cbf,
2.21      frystyk   133:                              void * param, ms_t millis, BOOL relative,
                    134:                              BOOL repetitive)
2.1       frystyk   135: {
2.7       eric      136:     HTList * last;
                    137:     HTList * cur;
2.2       frystyk   138:     ms_t now = HTGetTimeInMillis();
2.3       eric      139:     ms_t expires;
2.7       eric      140:     HTTimer * pres;
2.3       eric      141: 
2.7       eric      142:     CHECKME(timer);
2.3       eric      143:     expires = millis;
2.17      frystyk   144:     if (relative)
                    145:        expires += now;
                    146:     else
                    147:        millis = expires-now;
2.3       eric      148: 
                    149:     if (Timers == NULL)
                    150:        Timers = HTList_new();
                    151: 
                    152:     if (timer) {
                    153: 
                    154:        /*      if a timer is specified, it should already exist
                    155:         */
2.7       eric      156:        if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
2.19      frystyk   157:            HTDebugBreak(__FILE__, __LINE__, "Timer %p not found\n", timer);
2.7       eric      158:            CLEARME(timer);
2.3       eric      159:            return NULL;
2.7       eric      160:        }
                    161:        HTList_quickRemoveElement(cur, last);
2.11      frystyk   162:        if (THD_TRACE)
                    163:            HTTrace("Timer....... Found timer %p with callback %p, context %p, and %s timeout %d\n",
                    164:                    timer, cbf, param, relative ? "relative" : "absolute", millis);
2.7       eric      165:        /* could optimize by sorting from last when ((HTList *)(last->object))->expires < expires (most common case) */
2.3       eric      166:     } else {
                    167: 
                    168:        /*      create a new timer
                    169:         */
2.1       frystyk   170:        if ((timer = (HTTimer *) HT_CALLOC(1, sizeof(HTTimer))) == NULL)
2.2       frystyk   171:            HT_OUTOFMEM("HTTimer_new");
2.7       eric      172:        last = Timers;
2.11      frystyk   173:        if (THD_TRACE)
2.21      frystyk   174:            HTTrace("Timer....... Created %s timer %p with callback %p, context %p, and %s timeout %d\n",
                    175:                    repetitive ? "repetitive" : "one shot",
                    176:                    timer, cbf, param,
                    177:                    relative ? "relative" : "absolute", millis);
2.1       frystyk   178:     }
2.16      frystyk   179: 
                    180:     /*
                    181:     **  Sort new element into list
                    182:     */
2.7       eric      183:     for (cur = last; 
                    184:         (pres = (HTTimer *) HTList_nextObject(cur)) != NULL && pres->expires < expires; 
                    185:         last = cur);
2.16      frystyk   186: 
                    187:     /*
                    188:     **  If the expiration is 0 then we still register it but dispatch it immediately.
                    189:     */
                    190:     if (!millis) if (THD_TRACE) HTTrace("Timer....... Timeout is 0 - expires NOW\n");
                    191: 
2.3       eric      192:     timer->expires = expires;
2.1       frystyk   193:     timer->cbf = cbf;
                    194:     timer->param = param;
                    195:     timer->millis = millis;
                    196:     timer->relative = relative;
2.21      frystyk   197:     timer->repetitive = repetitive;
2.7       eric      198:     SETME(timer);
2.3       eric      199: 
                    200:     /*
                    201:     ** add to list if timer is new
                    202:     */
2.7       eric      203:     HTList_addObject(last, (void *)timer);
2.9       frystyk   204: 
                    205:     /*
                    206:     **  Call any platform specific timer handler
                    207:     */
                    208:     if (SetPlatformTimer) SetPlatformTimer(timer);
                    209: 
2.23    ! frystyk   210:     /* Check if the timer object has already expired. If so then dispatch */
        !           211:     if (timer->expires <= now) Timer_dispatch(cur, last);
2.16      frystyk   212: 
2.7       eric      213:     CLEARME(timer);
2.1       frystyk   214:     return timer;
                    215: }
                    216: 
                    217: 
2.7       eric      218: PUBLIC BOOL HTTimer_refresh (HTTimer * timer, ms_t now)
                    219: {
2.21      frystyk   220:     if (timer == NULL || timer->repetitive == NO)
2.7       eric      221:        return NO;
2.21      frystyk   222:     if (HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES, YES) == NULL)
2.7       eric      223:        return NO;
                    224:     return YES;
                    225: }
                    226: 
2.1       frystyk   227: PUBLIC BOOL HTTimer_deleteAll (void)
                    228: {
2.3       eric      229:     HTList * cur = Timers;
                    230:     HTTimer * pres;
                    231:     if (Timers) {
                    232:        while ((pres = (HTTimer *) HTList_nextObject(cur))) {
2.9       frystyk   233: 
                    234:            /*
                    235:            **  Call any platform specific timer handler
                    236:            */
                    237:            if (DeletePlatformTimer) DeletePlatformTimer(pres);
2.3       eric      238:            HT_FREE(pres);
2.1       frystyk   239:        }
2.3       eric      240:        HTList_delete(Timers);
                    241:        Timers = NULL;
2.1       frystyk   242:        return YES;
                    243:     }
                    244:     return NO;
                    245: }
                    246: 
2.3       eric      247: PUBLIC int HTTimer_dispatch (HTTimer * timer)
                    248: {
                    249:     HTList * cur;
                    250:     HTList * last = Timers;
                    251:     cur = HTList_elementOf(Timers, (void *)timer, &last);
2.23    ! frystyk   252:     return Timer_dispatch(cur, last);
2.21      frystyk   253: }
                    254: 
                    255: /*
                    256: **  Check if the timer object has already expired
                    257: */
                    258: PUBLIC BOOL HTTimer_hasTimerExpired (HTTimer * timer)
                    259: {
                    260:     return (timer && timer->expires <= HTGetTimeInMillis());
2.1       frystyk   261: }
                    262: 
2.7       eric      263: PUBLIC int HTTimer_next (ms_t * pSoonest)
2.1       frystyk   264: {
2.17      frystyk   265:     HTList * cur = Timers;
                    266:     HTList * last = Timers;
2.7       eric      267:     HTTimer * pres;
2.3       eric      268:     ms_t now = HTGetTimeInMillis();
2.7       eric      269:     int ret = HT_OK;
2.3       eric      270: 
2.17      frystyk   271:     /*
                    272:     **  Dispatch all timers that have expired
                    273:     */
                    274:     while (Timers && (pres = (HTTimer *) HTList_nextObject(cur))) {
                    275:        if (pres->expires <= now) {
2.23    ! frystyk   276:            if ((ret = Timer_dispatch(cur, last)) != HT_OK) break;
2.17      frystyk   277:            cur = last = Timers;
                    278:        } else {
                    279:            last = cur;
                    280:        }       
                    281:     }
2.3       eric      282: 
2.7       eric      283:     if (pSoonest) {
                    284:        /*
                    285:        **      First element in Timers is the next to expire.
2.3       eric      286:        */
2.8       frystyk   287:        HTList * cur = Timers;  /* for now */
                    288:        pres = (HTTimer *) HTList_nextObject(cur);
2.7       eric      289:        *pSoonest = pres ? pres->expires - now : 0;
2.1       frystyk   290:     }
2.7       eric      291:     return ret;
2.1       frystyk   292: }
2.12      eric      293: 
2.13      frystyk   294: #ifdef WATCH_RECURSION
2.12      eric      295: extern void CheckSockEvent(HTTimer * timer, HTTimerCallback * cbf, void * param);
2.13      frystyk   296: PRIVATE void CheckTimers(void)
2.12      eric      297: {
                    298:     HTList * cur = Timers;
                    299:     HTTimer * pres;
                    300:     while ((pres = (HTTimer *) HTList_nextObject(cur))) {
                    301:        CheckSockEvent(pres, pres->cbf, pres->param);
                    302:     }
                    303: }
2.13      frystyk   304: #endif

Webmaster