[BACK] Return to HTTimer.c CVS log [TXT] [DIR] Up to [Public] / libwww / Library / src

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

AltStyle によって変換されたページ (->オリジナル) /