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

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

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.27 ! kahan 6: **   @(#) $Id: HTTimer.c,v 2.26 1999年02月22日 22:10:12 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.26 frystyk 41: #define CHECKME(timer) if (InTimer != NULL) HTDEBUGBREAK("check timer\n"); InTimer = timer;
 42: #define CLEARME(timer) if (InTimer != timer) HTDEBUGBREAK("clear timer\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
2.26 frystyk 100:     HTDEBUGBREAK("Timer dispatch couldn't find a timer\n");
2.23 frystyk 101: #endif
 102:     CLEARME(timer);
 103:    return HT_ERROR;
 104:   }
2.27 ! kahan 105: #ifdef WWW_WIN_ASYNC
 ! 106:   /* 2000年07月31日 Jens Meggers (meggers@firepad.com):
 ! 107:    On Windows, timers are always repetitive, so we have to delete the 
 ! 108:    timer */
 ! 109:   DeletePlatformTimer(timer);
 ! 110: #endif /* WWW_WIN_ASYNC */
2.23 frystyk 111:   if (timer->repetitive)
 112:    HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES, YES);
 113:   else
 114:    HTList_quickRemoveElement(cur, last);
2.26 frystyk 115:   HTTRACE(THD_TRACE, "Timer....... Dispatch timer %p\n" _ timer);
2.23 frystyk 116:   ret = (*timer->cbf) (timer, timer->param, HTEvent_TIMEOUT);
 117:   return ret;
 118: }
 119: 
2.9 frystyk 120: PUBLIC BOOL HTTimer_registerSetTimerCallback (HTTimerSetCallback * cbf)
2.4 eric 121: {
2.26 frystyk 122:   HTTRACE(CORE_TRACE, "Timer....... registering %p as timer set cbf\n" _ cbf);
2.9 frystyk 123:   if (cbf) {
 124:    SetPlatformTimer = cbf;
 125:    return YES;
 126:   }
 127:   return NO;
2.4 eric 128: }
 129: 
2.9 frystyk 130: PUBLIC BOOL HTTimer_registerDeleteTimerCallback (HTTimerSetCallback * cbf)
2.4 eric 131: {
2.26 frystyk 132:   HTTRACE(CORE_TRACE, "Timer....... registering %p as timer delete cbf\n" _ cbf);
2.9 frystyk 133:   if (cbf) {
 134:    DeletePlatformTimer = cbf;
 135:    return YES;
 136:   }
 137:   return NO;
2.10 eric 138: }
 139: 
2.24 frystyk 140: PUBLIC ms_t HTTimer_expiresRelative (HTTimer * timer)
 141: {
 142:   return timer ? timer->millis : 0;
 143: }
 144: 
 145: PUBLIC ms_t HTTimer_expiresAbsolute (HTTimer * timer)
 146: {
 147:   return timer ? timer->expires : 0;
 148: }
 149: 
 150: PUBLIC HTTimerCallback * HTTimer_callback (HTTimer * timer)
 151: {
 152:   return timer ? timer->cbf : NULL;
 153: }
 154: 
 155: PUBLIC BOOL HTTimer_isRelative (HTTimer * timer)
2.10 eric 156: {
2.24 frystyk 157:   return timer ? timer->relative : NO;
2.4 eric 158: }
 159: 
2.1 frystyk 160: PUBLIC BOOL HTTimer_delete (HTTimer * timer)
 161: {
2.3 eric 162:   HTList * last;
 163:   HTList * cur;
2.7 eric 164:   CHECKME(timer);
2.23 frystyk 165:   if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) CLEARME(timer);
2.18 frystyk 166:   if (HTList_quickRemoveElement(cur, last)) {
2.26 frystyk 167:    HTTRACE(THD_TRACE, "Timer....... Deleted active timer %p\n" _ timer);
2.18 frystyk 168:   } else { 
2.26 frystyk 169:    HTTRACE(THD_TRACE, "Timer....... Deleted expired timer %p\n" _ timer);
2.18 frystyk 170:   }
2.9 frystyk 171: 
 172:   /*
 173:   ** Call any platform specific timer handler
 174:   */
 175:   if (DeletePlatformTimer) DeletePlatformTimer(timer);
 176: 
2.7 eric 177:   CLEARME(timer);
2.3 eric 178:   HT_FREE(timer);
 179:   return YES;
2.1 frystyk 180: }
 181: 
 182: PUBLIC HTTimer * HTTimer_new (HTTimer * timer, HTTimerCallback * cbf,
2.21 frystyk 183:               void * param, ms_t millis, BOOL relative,
 184:               BOOL repetitive)
2.1 frystyk 185: {
2.7 eric 186:   HTList * last;
 187:   HTList * cur;
2.2 frystyk 188:   ms_t now = HTGetTimeInMillis();
2.3 eric 189:   ms_t expires;
2.7 eric 190:   HTTimer * pres;
2.3 eric 191: 
2.7 eric 192:   CHECKME(timer);
2.3 eric 193:   expires = millis;
2.17 frystyk 194:   if (relative)
 195:    expires += now;
 196:   else
 197:    millis = expires-now;
2.3 eric 198: 
 199:   if (Timers == NULL)
 200:    Timers = HTList_new();
 201: 
 202:   if (timer) {
 203: 
 204:    /*   if a timer is specified, it should already exist
 205:     */
2.7 eric 206:    if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
2.26 frystyk 207:      HTDEBUGBREAK("Timer %p not found\n" _ timer);
2.7 eric 208:      CLEARME(timer);
2.3 eric 209:      return NULL;
2.7 eric 210:    }
 211:    HTList_quickRemoveElement(cur, last);
2.26 frystyk 212:    HTTRACE(THD_TRACE, "Timer....... Found timer %p with callback %p, context %p, and %s timeout %d\n" _ 
 213:          timer _ cbf _ param _ relative ? "relative" : "absolute" _ millis);
2.7 eric 214:    /* could optimize by sorting from last when ((HTList *)(last->object))->expires < expires (most common case) */
2.3 eric 215:   } else {
 216: 
 217:    /*   create a new timer
 218:     */
2.1 frystyk 219:    if ((timer = (HTTimer *) HT_CALLOC(1, sizeof(HTTimer))) == NULL)
2.2 frystyk 220:      HT_OUTOFMEM("HTTimer_new");
2.7 eric 221:    last = Timers;
2.26 frystyk 222:    HTTRACE(THD_TRACE, "Timer....... Created %s timer %p with callback %p, context %p, and %s timeout %d\n" _ 
 223:          repetitive ? "repetitive" : "one shot" _ 
 224:          timer _ cbf _ param _ 
 225:          relative ? "relative" : "absolute" _ millis);
2.1 frystyk 226:   }
2.16 frystyk 227: 
 228:   /*
 229:   ** Sort new element into list
 230:   */
2.7 eric 231:   for (cur = last; 
 232:     (pres = (HTTimer *) HTList_nextObject(cur)) != NULL && pres->expires < expires; 
 233:     last = cur);
2.16 frystyk 234: 
 235:   /*
 236:   ** If the expiration is 0 then we still register it but dispatch it immediately.
 237:   */
2.26 frystyk 238:   if (!millis) HTTRACE(THD_TRACE, "Timer....... Timeout is 0 - expires NOW\n");
2.16 frystyk 239: 
2.3 eric 240:   timer->expires = expires;
2.1 frystyk 241:   timer->cbf = cbf;
 242:   timer->param = param;
 243:   timer->millis = millis;
 244:   timer->relative = relative;
2.21 frystyk 245:   timer->repetitive = repetitive;
2.7 eric 246:   SETME(timer);
2.3 eric 247: 
 248:   /*
 249:   ** add to list if timer is new
 250:   */
2.7 eric 251:   HTList_addObject(last, (void *)timer);
2.9 frystyk 252: 
 253:   /*
 254:   ** Call any platform specific timer handler
 255:   */
 256:   if (SetPlatformTimer) SetPlatformTimer(timer);
 257: 
2.23 frystyk 258:   /* Check if the timer object has already expired. If so then dispatch */
 259:   if (timer->expires <= now) Timer_dispatch(cur, last);
2.16 frystyk 260: 
2.7 eric 261:   CLEARME(timer);
2.1 frystyk 262:   return timer;
 263: }
 264: 
 265: 
2.7 eric 266: PUBLIC BOOL HTTimer_refresh (HTTimer * timer, ms_t now)
 267: {
2.21 frystyk 268:   if (timer == NULL || timer->repetitive == NO)
2.7 eric 269:    return NO;
2.21 frystyk 270:   if (HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES, YES) == NULL)
2.7 eric 271:    return NO;
 272:   return YES;
 273: }
 274: 
2.1 frystyk 275: PUBLIC BOOL HTTimer_deleteAll (void)
 276: {
2.3 eric 277:   HTList * cur = Timers;
 278:   HTTimer * pres;
 279:   if (Timers) {
 280:    while ((pres = (HTTimer *) HTList_nextObject(cur))) {
2.9 frystyk 281: 
 282:      /*
 283:      ** Call any platform specific timer handler
 284:      */
 285:      if (DeletePlatformTimer) DeletePlatformTimer(pres);
2.3 eric 286:      HT_FREE(pres);
2.1 frystyk 287:    }
2.3 eric 288:    HTList_delete(Timers);
 289:    Timers = NULL;
2.1 frystyk 290:    return YES;
 291:   }
 292:   return NO;
 293: }
 294: 
2.3 eric 295: PUBLIC int HTTimer_dispatch (HTTimer * timer)
 296: {
 297:   HTList * cur;
 298:   HTList * last = Timers;
 299:   cur = HTList_elementOf(Timers, (void *)timer, &last);
2.23 frystyk 300:   return Timer_dispatch(cur, last);
2.21 frystyk 301: }
 302: 
 303: /*
 304: ** Check if the timer object has already expired
 305: */
 306: PUBLIC BOOL HTTimer_hasTimerExpired (HTTimer * timer)
 307: {
 308:   return (timer && timer->expires <= HTGetTimeInMillis());
2.1 frystyk 309: }
 310: 
2.7 eric 311: PUBLIC int HTTimer_next (ms_t * pSoonest)
2.1 frystyk 312: {
2.17 frystyk 313:   HTList * cur = Timers;
 314:   HTList * last = Timers;
2.7 eric 315:   HTTimer * pres;
2.3 eric 316:   ms_t now = HTGetTimeInMillis();
2.7 eric 317:   int ret = HT_OK;
2.3 eric 318: 
2.17 frystyk 319:   /*
 320:   ** Dispatch all timers that have expired
 321:   */
 322:   while (Timers && (pres = (HTTimer *) HTList_nextObject(cur))) {
 323:    if (pres->expires <= now) {
2.23 frystyk 324:      if ((ret = Timer_dispatch(cur, last)) != HT_OK) break;
2.17 frystyk 325:      cur = last = Timers;
 326:    } else {
 327:      last = cur;
 328:    }    
 329:   }
2.3 eric 330: 
2.7 eric 331:   if (pSoonest) {
 332:    /*
 333:    **   First element in Timers is the next to expire.
2.3 eric 334:    */
2.8 frystyk 335:    HTList * cur = Timers; /* for now */
 336:    pres = (HTTimer *) HTList_nextObject(cur);
2.7 eric 337:    *pSoonest = pres ? pres->expires - now : 0;
2.1 frystyk 338:   }
2.7 eric 339:   return ret;
2.1 frystyk 340: }
2.12 eric 341: 
2.13 frystyk 342: #ifdef WATCH_RECURSION
2.12 eric 343: extern void CheckSockEvent(HTTimer * timer, HTTimerCallback * cbf, void * param);
2.13 frystyk 344: PRIVATE void CheckTimers(void)
2.12 eric 345: {
 346:   HTList * cur = Timers;
 347:   HTTimer * pres;
 348:   while ((pres = (HTTimer *) HTList_nextObject(cur))) {
 349:    CheckSockEvent(pres, pres->cbf, pres->param);
 350:   }
 351: }
2.13 frystyk 352: #endif
2.25 kahan 353: 
 354: 

Webmaster

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