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

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

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