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