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

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

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