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

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

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.10 ! eric 6: **   @(#) $Id: HTTimer.c,v 2.9 1996年12月27日 16:13:23 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.7 eric 39: #if 1 /* WATCH_RECURSION */
 40: 
 41: PRIVATE HTTimer * InTimer = NULL;
 42: #define CHECKME(timer) if (InTimer != NULL) HTDebugBreak(); InTimer = timer;
 43: #define CLEARME(timer) if (InTimer != timer) HTDebugBreak(); InTimer = NULL;
 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:    HTDebugBreak();
 89:    CLEARME(timer);
2.3 eric 90:    return NO;
2.7 eric 91:   }
2.3 eric 92:   HTList_quickRemoveElement(cur, last);
2.9 frystyk 93: 
 94:   /*
 95:   ** Call any platform specific timer handler
 96:   */
 97:   if (DeletePlatformTimer) DeletePlatformTimer(timer);
 98: 
2.3 eric 99:   if (THD_TRACE) HTTrace("Timer....... Deleted timer %p\n", timer);
2.7 eric 100:   CLEARME(timer);
2.3 eric 101:   HT_FREE(timer);
 102:   return YES;
2.1 frystyk 103: }
 104: 
 105: PUBLIC HTTimer * HTTimer_new (HTTimer * timer, HTTimerCallback * cbf,
2.2 frystyk 106:               void * param, ms_t millis, BOOL relative)
2.1 frystyk 107: {
2.7 eric 108:   HTList * last;
 109:   HTList * cur;
2.2 frystyk 110:   ms_t now = HTGetTimeInMillis();
2.3 eric 111:   ms_t expires;
2.7 eric 112:   HTTimer * pres;
2.3 eric 113: 
2.7 eric 114:   CHECKME(timer);
2.3 eric 115:   expires = millis;
 116:   if (relative) expires += now;
 117: 
 118:   if (Timers == NULL)
 119:    Timers = HTList_new();
 120: 
 121:   if (timer) {
 122: 
 123:    /*   if a timer is specified, it should already exist
 124:     */
2.7 eric 125:    if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
 126:      HTDebugBreak();
 127:      CLEARME(timer);
2.3 eric 128:      return NULL;
2.7 eric 129:    }
 130:    HTList_quickRemoveElement(cur, last);
 131:    /* could optimize by sorting from last when ((HTList *)(last->object))->expires < expires (most common case) */
2.3 eric 132:   } else {
 133: 
 134:    /*   create a new timer
 135:     */
2.1 frystyk 136:    if ((timer = (HTTimer *) HT_CALLOC(1, sizeof(HTTimer))) == NULL)
2.2 frystyk 137:      HT_OUTOFMEM("HTTimer_new");
2.7 eric 138:    last = Timers;
2.1 frystyk 139:   }
2.7 eric 140:   /* sort new element into list
 141:   */
 142:   for (cur = last; 
 143:     (pres = (HTTimer *) HTList_nextObject(cur)) != NULL && pres->expires < expires; 
 144:     last = cur);
 145:   if (THD_TRACE)
 146:    HTTrace("Timer....... Created timer %p with callback %p, context %p, and %s timeout %d\n",
 147:         timer, cbf, param, relative ? "relative" : "absolute", millis);
2.1 frystyk 148:   if (!millis) return timer;
2.3 eric 149:   timer->expires = expires;
2.1 frystyk 150:   timer->cbf = cbf;
 151:   timer->param = param;
 152:   timer->millis = millis;
 153:   timer->relative = relative;
2.7 eric 154:   SETME(timer);
2.3 eric 155:   /* may already be obsolete
 156:   */
2.1 frystyk 157:   if (timer->expires <= now) {
 158:    int status;
2.7 eric 159:    if ((status = (*timer->cbf)(timer, timer->param, HTEvent_TIMEOUT)) != HT_OK) {
2.3 eric 160:      if (cur)
 161:        HTList_quickRemoveElement(cur, last);
 162:      HT_FREE(timer);
2.7 eric 163:      CLEARME(timer);
2.1 frystyk 164:      return NULL;
 165:    }
 166:   }
2.3 eric 167: 
 168:   /*
 169:   ** add to list if timer is new
 170:   */
2.7 eric 171:   HTList_addObject(last, (void *)timer);
2.9 frystyk 172: 
 173:   /*
 174:   ** Call any platform specific timer handler
 175:   */
 176:   if (SetPlatformTimer) SetPlatformTimer(timer);
 177: 
2.7 eric 178:   CLEARME(timer);
2.1 frystyk 179:   return timer;
 180: }
 181: 
 182: 
2.7 eric 183: PUBLIC BOOL HTTimer_refresh (HTTimer * timer, ms_t now)
 184: {
 185:   if (timer == NULL || timer->relative == NO)
 186:    return NO;
 187:   if (HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES) == NULL)
 188:    return NO;
 189:   return YES;
 190: }
 191: 
2.1 frystyk 192: PUBLIC BOOL HTTimer_deleteAll (void)
 193: {
2.3 eric 194:   HTList * cur = Timers;
 195:   HTTimer * pres;
 196:   if (Timers) {
 197:    while ((pres = (HTTimer *) HTList_nextObject(cur))) {
2.9 frystyk 198: 
 199:      /*
 200:      ** Call any platform specific timer handler
 201:      */
 202:      if (DeletePlatformTimer) DeletePlatformTimer(pres);
2.3 eric 203:      HT_FREE(pres);
2.1 frystyk 204:    }
2.3 eric 205:    HTList_delete(Timers);
 206:    Timers = NULL;
2.1 frystyk 207:    return YES;
 208:   }
 209:   return NO;
 210: }
 211: 
 212: /*
 213: ** When a timer has expired, we dispatch the event handler and re-register the
 214: ** timer with the next expiration time.
 215: */
2.3 eric 216: PRIVATE int Timer_dispatch (HTList * cur, HTList * last, int now)
2.1 frystyk 217: {
2.3 eric 218:   HTTimer * timer;
 219:   int ret;
 220: 
 221:   timer = (HTTimer *)HTList_objectOf(cur);
2.7 eric 222:   if (timer == NULL) {
 223:    HTDebugBreak();
 224:    CLEARME(timer);
2.3 eric 225:    return HT_ERROR;
2.7 eric 226:   }
2.1 frystyk 227:   if (timer->relative)
 228:    HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES);
2.3 eric 229:   else
 230:    HTList_quickRemoveElement(cur, last);
2.1 frystyk 231:   if (THD_TRACE) HTTrace("Timer....... Dispatch timer %p\n", timer);
2.7 eric 232: /*  CHECKME(timer); all entries to this function are now re-entry save */
 233:   ret = (*timer->cbf) (timer, timer->param, HTEvent_TIMEOUT);
 234: /*  CLEARME(timer); */
2.3 eric 235:   if (!timer->relative)
 236:    HT_FREE(timer);
 237:   return ret;
 238: }
 239: 
 240: PUBLIC int HTTimer_dispatch (HTTimer * timer)
 241: {
 242:   HTList * cur;
 243:   HTList * last = Timers;
 244:   ms_t now = HTGetTimeInMillis();
 245: 
 246:   cur = HTList_elementOf(Timers, (void *)timer, &last);
 247:   return Timer_dispatch(cur, last, now);
2.1 frystyk 248: }
 249: 
2.7 eric 250: PUBLIC int HTTimer_next (ms_t * pSoonest)
2.1 frystyk 251: {
2.7 eric 252:   HTList * cur;
 253:   HTList * last;
 254:   HTTimer * pres;
2.3 eric 255:   ms_t now = HTGetTimeInMillis();
2.7 eric 256:   int ret = HT_OK;
 257:   HTList * head;
2.3 eric 258: 
 259:   if (Timers == NULL)
2.7 eric 260:    return HT_OK;
2.3 eric 261: 
2.7 eric 262:   /* The Timers list may be modified during a dispatch
 263:   ** so we have to build an intermediate list
 264:   */
 265:   head = last = HTList_new();
 266:   cur = Timers;
2.3 eric 267:   while ((pres = (HTTimer *) HTList_nextObject(cur)) && pres->expires <= now) {
2.7 eric 268:    HTList_addObject(last, (void *)pres);
 269:    last = HTList_nextObject(last);
 270:   }
 271: 
 272:   /*
 273:   ** Now dispatch the intermediate list
 274:   */
 275:   cur = last = head;
 276:   while ((pres = (HTTimer *) HTList_nextObject(cur)) && ret == HT_OK) {
 277:    ret = Timer_dispatch(cur, last, now);
2.3 eric 278:    last = cur;
2.2 frystyk 279:   }
2.3 eric 280: 
2.7 eric 281:   if (pSoonest) {
 282:    /*
 283:    **   First element in Timers is the next to expire.
2.3 eric 284:    */
2.8 frystyk 285:    HTList * cur = Timers; /* for now */
 286:    pres = (HTTimer *) HTList_nextObject(cur);
2.7 eric 287:    *pSoonest = pres ? pres->expires - now : 0;
2.1 frystyk 288:   }
2.7 eric 289:   HTList_delete(head);
 290:   return ret;
2.1 frystyk 291: }

Webmaster

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