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

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

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

Webmaster

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