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

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

Webmaster