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

2.24      frystyk     1: /*
                      2: **     TIMER MANAGER
2.1       frystyk     3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.25    ! kahan       6: **     @(#) $Id: HTTimer.c,v 2.24 1999/02/16 13:16:55 frystyk Exp $
2.1       frystyk     7: **
2.24      frystyk     8: **     Timers based on the X server timers
2.1       frystyk     9: **
                     10: ** Authors:
                     11: **     EGP     Eric Prud'hommeaux (eric@w3.org)
2.24      frystyk    12: **     HFN     Henrik Frystyk Nielsen
2.1       frystyk    13: ** Bugs
                     14: **
                     15: */
                     16: 
                     17: /* Implementation dependent include files */
2.20      frystyk    18: #include "wwwsys.h"
2.1       frystyk    19: #include "WWWUtil.h"
                     20: #include "WWWCore.h"
                     21: #include "HTReqMan.h"
                     22: #include "HTTimer.h"                                    /* Implemented here */
                     23: 
                     24: struct _HTTimer {
2.2       frystyk    25:     ms_t       millis;         /* Relative value in millis */
                     26:     ms_t       expires;        /* Absolute value in millis */
2.1       frystyk    27:     BOOL       relative;
2.21      frystyk    28:     BOOL       repetitive;
2.1       frystyk    29:     void *     param;          /* Client supplied context */
                     30:     HTTimerCallback * cbf;
                     31: };
                     32: 
2.3       eric       33: PRIVATE HTList * Timers = NULL;                           /* List of timers */
2.1       frystyk    34: 
2.9       frystyk    35: PRIVATE HTTimerSetCallback * SetPlatformTimer = NULL;
                     36: PRIVATE HTTimerSetCallback * DeletePlatformTimer = NULL;
                     37: 
2.24      frystyk    38: #ifdef WATCH_RECURSION
2.7       eric       39: 
                     40: PRIVATE HTTimer * InTimer = NULL;
2.19      frystyk    41: #define CHECKME(timer) if (InTimer != NULL) HTDebugBreak(__FILE__, __LINE__, "\n"); InTimer = timer;
                     42: #define CLEARME(timer) if (InTimer != timer) HTDebugBreak(__FILE, __LINE__, "\n"); InTimer = NULL;
2.7       eric       43: #define SETME(timer) InTimer = timer;
                     44: 
                     45: #else /* WATCH_RECURSION */
                     46: 
                     47: #define CHECKME(timer)
                     48: #define CLEARME(timer)
                     49: #define SETME(timer)
                     50: 
                     51: #endif /* !WATCH_RECURSION */
2.25    ! kahan      52: 
        !            53: /* JK: used by Amaya */
        !            54: PUBLIC BOOL HTTimer_expireAll (void)
        !            55: {
        !            56:   HTList * cur;
        !            57:   HTTimer * timer;
        !            58:   if (Timers) {
        !            59:     /*
        !            60:     **  first delete all plattform specific timers to
        !            61:     **  avoid having a concurrent callback
        !            62:     */
        !            63:     cur = Timers;
        !            64:     while ((timer = (HTTimer *) HTList_nextObject(cur))) {
        !            65:       if (DeletePlatformTimer) DeletePlatformTimer(timer);
        !            66:     }
        !            67:  
        !            68:     /*
        !            69:     ** simulate a timer timeout thru timer_dispatch
        !            70:     ** to kill its context
        !            71:     */
        !            72:     cur = Timers;
        !            73:     while ((timer = (HTTimer *) HTList_nextObject(cur))) {
        !            74:           /* avoid having it being refreshed */
        !            75:       timer->repetitive = NO;
        !            76:       HTTimer_dispatch (timer);
        !            77:       /* as the timer is erased, we start again from the top of the list */
        !            78:       cur = Timers;
        !            79:     }
        !            80:     return YES;
        !            81:   }
        !            82:   return NO;
        !            83: }
        !            84: 
2.1       frystyk    85: /* ------------------------------------------------------------------------- */
                     86: 
2.23      frystyk    87: /*
                     88: **  When a timer has expired, we dispatch the event handler and re-register the
                     89: **  timer with the next expiration time if repetitive. Otherwise we just leave
                     90: **  it
                     91: */
                     92: PRIVATE int Timer_dispatch (HTList * cur, HTList * last)
                     93: {
                     94:     HTTimer * timer;
                     95:     int ret = HT_ERROR;
                     96: 
                     97:     timer = (HTTimer *)HTList_objectOf(cur);
                     98:     if (timer == NULL) {
                     99: #if 0
                    100:         HTDebugBreak(__FILE__, __LINE__, "Timer dispatch couldn't find a timer\n");
                    101: #endif
                    102:         CLEARME(timer);
                    103:        return HT_ERROR;
                    104:     }
                    105:     if (timer->repetitive)
                    106:        HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES, YES);
                    107:     else
                    108:        HTList_quickRemoveElement(cur, last);
                    109:     if (THD_TRACE) HTTrace("Timer....... Dispatch timer %p\n", timer);
                    110:     ret = (*timer->cbf) (timer, timer->param, HTEvent_TIMEOUT);
                    111:     return ret;
                    112: }
                    113: 
2.9       frystyk   114: PUBLIC BOOL HTTimer_registerSetTimerCallback (HTTimerSetCallback * cbf)
2.4       eric      115: {
2.9       frystyk   116:     if (CORE_TRACE) HTTrace("Timer....... registering %p as timer set cbf\n", cbf);
                    117:     if (cbf) {
                    118:        SetPlatformTimer = cbf;
                    119:        return YES;
                    120:     }
                    121:     return NO;
2.4       eric      122: }
                    123: 
2.9       frystyk   124: PUBLIC BOOL HTTimer_registerDeleteTimerCallback (HTTimerSetCallback * cbf)
2.4       eric      125: {
2.9       frystyk   126:     if (CORE_TRACE) HTTrace("Timer....... registering %p as timer delete cbf\n", cbf);
                    127:     if (cbf) {
                    128:        DeletePlatformTimer = cbf;
                    129:        return YES;
                    130:     }
                    131:     return NO;
2.10      eric      132: }
                    133: 
2.24      frystyk   134: PUBLIC ms_t HTTimer_expiresRelative (HTTimer * timer)
                    135: {
                    136:     return timer ? timer->millis : 0;
                    137: }
                    138: 
                    139: PUBLIC ms_t HTTimer_expiresAbsolute (HTTimer * timer)
                    140: {
                    141:     return timer ? timer->expires : 0;
                    142: }
                    143: 
                    144: PUBLIC HTTimerCallback * HTTimer_callback (HTTimer * timer)
                    145: {
                    146:     return timer ? timer->cbf : NULL;
                    147: }
                    148: 
                    149: PUBLIC BOOL HTTimer_isRelative (HTTimer * timer)
2.10      eric      150: {
2.24      frystyk   151:     return timer ? timer->relative : NO;
2.4       eric      152: }
                    153: 
2.1       frystyk   154: PUBLIC BOOL HTTimer_delete (HTTimer * timer)
                    155: {
2.3       eric      156:     HTList * last;
                    157:     HTList * cur;
2.7       eric      158:     CHECKME(timer);
2.23      frystyk   159:     if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) CLEARME(timer);
2.18      frystyk   160:     if (HTList_quickRemoveElement(cur, last)) {
2.23      frystyk   161:        if (THD_TRACE) HTTrace("Timer....... Deleted active timer %p\n", timer);
2.18      frystyk   162:     } else { 
2.23      frystyk   163:        if (THD_TRACE) HTTrace("Timer....... Deleted expired timer %p\n", timer);
2.18      frystyk   164:     }
2.9       frystyk   165: 
                    166:     /*
                    167:     **  Call any platform specific timer handler
                    168:     */
                    169:     if (DeletePlatformTimer) DeletePlatformTimer(timer);
                    170: 
2.7       eric      171:     CLEARME(timer);
2.3       eric      172:     HT_FREE(timer);
                    173:     return YES;
2.1       frystyk   174: }
                    175: 
                    176: PUBLIC HTTimer * HTTimer_new (HTTimer * timer, HTTimerCallback * cbf,
2.21      frystyk   177:                              void * param, ms_t millis, BOOL relative,
                    178:                              BOOL repetitive)
2.1       frystyk   179: {
2.7       eric      180:     HTList * last;
                    181:     HTList * cur;
2.2       frystyk   182:     ms_t now = HTGetTimeInMillis();
2.3       eric      183:     ms_t expires;
2.7       eric      184:     HTTimer * pres;
2.3       eric      185: 
2.7       eric      186:     CHECKME(timer);
2.3       eric      187:     expires = millis;
2.17      frystyk   188:     if (relative)
                    189:        expires += now;
                    190:     else
                    191:        millis = expires-now;
2.3       eric      192: 
                    193:     if (Timers == NULL)
                    194:        Timers = HTList_new();
                    195: 
                    196:     if (timer) {
                    197: 
                    198:        /*      if a timer is specified, it should already exist
                    199:         */
2.7       eric      200:        if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
2.19      frystyk   201:            HTDebugBreak(__FILE__, __LINE__, "Timer %p not found\n", timer);
2.7       eric      202:            CLEARME(timer);
2.3       eric      203:            return NULL;
2.7       eric      204:        }
                    205:        HTList_quickRemoveElement(cur, last);
2.11      frystyk   206:        if (THD_TRACE)
                    207:            HTTrace("Timer....... Found timer %p with callback %p, context %p, and %s timeout %d\n",
                    208:                    timer, cbf, param, relative ? "relative" : "absolute", millis);
2.7       eric      209:        /* could optimize by sorting from last when ((HTList *)(last->object))->expires < expires (most common case) */
2.3       eric      210:     } else {
                    211: 
                    212:        /*      create a new timer
                    213:         */
2.1       frystyk   214:        if ((timer = (HTTimer *) HT_CALLOC(1, sizeof(HTTimer))) == NULL)
2.2       frystyk   215:            HT_OUTOFMEM("HTTimer_new");
2.7       eric      216:        last = Timers;
2.11      frystyk   217:        if (THD_TRACE)
2.21      frystyk   218:            HTTrace("Timer....... Created %s timer %p with callback %p, context %p, and %s timeout %d\n",
                    219:                    repetitive ? "repetitive" : "one shot",
                    220:                    timer, cbf, param,
                    221:                    relative ? "relative" : "absolute", millis);
2.1       frystyk   222:     }
2.16      frystyk   223: 
                    224:     /*
                    225:     **  Sort new element into list
                    226:     */
2.7       eric      227:     for (cur = last; 
                    228:         (pres = (HTTimer *) HTList_nextObject(cur)) != NULL && pres->expires < expires; 
                    229:         last = cur);
2.16      frystyk   230: 
                    231:     /*
                    232:     **  If the expiration is 0 then we still register it but dispatch it immediately.
                    233:     */
                    234:     if (!millis) if (THD_TRACE) HTTrace("Timer....... Timeout is 0 - expires NOW\n");
                    235: 
2.3       eric      236:     timer->expires = expires;
2.1       frystyk   237:     timer->cbf = cbf;
                    238:     timer->param = param;
                    239:     timer->millis = millis;
                    240:     timer->relative = relative;
2.21      frystyk   241:     timer->repetitive = repetitive;
2.7       eric      242:     SETME(timer);
2.3       eric      243: 
                    244:     /*
                    245:     ** add to list if timer is new
                    246:     */
2.7       eric      247:     HTList_addObject(last, (void *)timer);
2.9       frystyk   248: 
                    249:     /*
                    250:     **  Call any platform specific timer handler
                    251:     */
                    252:     if (SetPlatformTimer) SetPlatformTimer(timer);
                    253: 
2.23      frystyk   254:     /* Check if the timer object has already expired. If so then dispatch */
                    255:     if (timer->expires <= now) Timer_dispatch(cur, last);
2.16      frystyk   256: 
2.7       eric      257:     CLEARME(timer);
2.1       frystyk   258:     return timer;
                    259: }
                    260: 
                    261: 
2.7       eric      262: PUBLIC BOOL HTTimer_refresh (HTTimer * timer, ms_t now)
                    263: {
2.21      frystyk   264:     if (timer == NULL || timer->repetitive == NO)
2.7       eric      265:        return NO;
2.21      frystyk   266:     if (HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES, YES) == NULL)
2.7       eric      267:        return NO;
                    268:     return YES;
                    269: }
                    270: 
2.1       frystyk   271: PUBLIC BOOL HTTimer_deleteAll (void)
                    272: {
2.3       eric      273:     HTList * cur = Timers;
                    274:     HTTimer * pres;
                    275:     if (Timers) {
                    276:        while ((pres = (HTTimer *) HTList_nextObject(cur))) {
2.9       frystyk   277: 
                    278:            /*
                    279:            **  Call any platform specific timer handler
                    280:            */
                    281:            if (DeletePlatformTimer) DeletePlatformTimer(pres);
2.3       eric      282:            HT_FREE(pres);
2.1       frystyk   283:        }
2.3       eric      284:        HTList_delete(Timers);
                    285:        Timers = NULL;
2.1       frystyk   286:        return YES;
                    287:     }
                    288:     return NO;
                    289: }
                    290: 
2.3       eric      291: PUBLIC int HTTimer_dispatch (HTTimer * timer)
                    292: {
                    293:     HTList * cur;
                    294:     HTList * last = Timers;
                    295:     cur = HTList_elementOf(Timers, (void *)timer, &last);
2.23      frystyk   296:     return Timer_dispatch(cur, last);
2.21      frystyk   297: }
                    298: 
                    299: /*
                    300: **  Check if the timer object has already expired
                    301: */
                    302: PUBLIC BOOL HTTimer_hasTimerExpired (HTTimer * timer)
                    303: {
                    304:     return (timer && timer->expires <= HTGetTimeInMillis());
2.1       frystyk   305: }
                    306: 
2.7       eric      307: PUBLIC int HTTimer_next (ms_t * pSoonest)
2.1       frystyk   308: {
2.17      frystyk   309:     HTList * cur = Timers;
                    310:     HTList * last = Timers;
2.7       eric      311:     HTTimer * pres;
2.3       eric      312:     ms_t now = HTGetTimeInMillis();
2.7       eric      313:     int ret = HT_OK;
2.3       eric      314: 
2.17      frystyk   315:     /*
                    316:     **  Dispatch all timers that have expired
                    317:     */
                    318:     while (Timers && (pres = (HTTimer *) HTList_nextObject(cur))) {
                    319:        if (pres->expires <= now) {
2.23      frystyk   320:            if ((ret = Timer_dispatch(cur, last)) != HT_OK) break;
2.17      frystyk   321:            cur = last = Timers;
                    322:        } else {
                    323:            last = cur;
                    324:        }       
                    325:     }
2.3       eric      326: 
2.7       eric      327:     if (pSoonest) {
                    328:        /*
                    329:        **      First element in Timers is the next to expire.
2.3       eric      330:        */
2.8       frystyk   331:        HTList * cur = Timers;  /* for now */
                    332:        pres = (HTTimer *) HTList_nextObject(cur);
2.7       eric      333:        *pSoonest = pres ? pres->expires - now : 0;
2.1       frystyk   334:     }
2.7       eric      335:     return ret;
2.1       frystyk   336: }
2.12      eric      337: 
2.13      frystyk   338: #ifdef WATCH_RECURSION
2.12      eric      339: extern void CheckSockEvent(HTTimer * timer, HTTimerCallback * cbf, void * param);
2.13      frystyk   340: PRIVATE void CheckTimers(void)
2.12      eric      341: {
                    342:     HTList * cur = Timers;
                    343:     HTTimer * pres;
                    344:     while ((pres = (HTTimer *) HTList_nextObject(cur))) {
                    345:        CheckSockEvent(pres, pres->cbf, pres->param);
                    346:     }
                    347: }
2.13      frystyk   348: #endif
2.25    ! kahan     349: 
        !           350: 

Webmaster