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

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

Webmaster