Annotation of libwww/Library/src/HTTimer.c, revision 2.17
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.17 ! frystyk 6: ** @(#) $Id: HTTimer.c,v 2.16 1997年03月21日 19:33:25 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.17 ! frystyk 39: #if 0 /* WATCH_RECURSION */
2.7 eric 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: CLEARME(timer);
2.3 eric 89: return NO;
2.7 eric 90: }
2.11 frystyk 91: if (HTList_quickRemoveElement(cur, last))
92: if (THD_TRACE) HTTrace("Timer....... Deleted timer %p\n", timer);
93: else
94: if (THD_TRACE) HTTrace("Timer....... Could not delete timer %p\n", timer);
2.9 frystyk 95:
96: /*
97: ** Call any platform specific timer handler
98: */
99: if (DeletePlatformTimer) DeletePlatformTimer(timer);
100:
2.7 eric 101: CLEARME(timer);
2.3 eric 102: HT_FREE(timer);
103: return YES;
2.1 frystyk 104: }
105:
106: PUBLIC HTTimer * HTTimer_new (HTTimer * timer, HTTimerCallback * cbf,
2.2 frystyk 107: void * param, ms_t millis, BOOL relative)
2.1 frystyk 108: {
2.7 eric 109: HTList * last;
110: HTList * cur;
2.2 frystyk 111: ms_t now = HTGetTimeInMillis();
2.3 eric 112: ms_t expires;
2.7 eric 113: HTTimer * pres;
2.3 eric 114:
2.7 eric 115: CHECKME(timer);
2.3 eric 116: expires = millis;
2.17 ! frystyk 117: if (relative)
! 118: expires += now;
! 119: else
! 120: millis = expires-now;
2.3 eric 121:
122: if (Timers == NULL)
123: Timers = HTList_new();
124:
125: if (timer) {
126:
127: /* if a timer is specified, it should already exist
128: */
2.7 eric 129: if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
130: HTDebugBreak();
131: CLEARME(timer);
2.3 eric 132: return NULL;
2.7 eric 133: }
134: HTList_quickRemoveElement(cur, last);
2.11 frystyk 135: if (THD_TRACE)
136: HTTrace("Timer....... Found timer %p with callback %p, context %p, and %s timeout %d\n",
137: timer, cbf, param, relative ? "relative" : "absolute", millis);
2.7 eric 138: /* could optimize by sorting from last when ((HTList *)(last->object))->expires < expires (most common case) */
2.3 eric 139: } else {
140:
141: /* create a new timer
142: */
2.1 frystyk 143: if ((timer = (HTTimer *) HT_CALLOC(1, sizeof(HTTimer))) == NULL)
2.2 frystyk 144: HT_OUTOFMEM("HTTimer_new");
2.7 eric 145: last = Timers;
2.11 frystyk 146: if (THD_TRACE)
147: HTTrace("Timer....... Created timer %p with callback %p, context %p, and %s timeout %d\n",
148: timer, cbf, param, relative ? "relative" : "absolute", millis);
2.1 frystyk 149: }
2.16 frystyk 150:
151: /*
152: ** Sort new element into list
153: */
2.7 eric 154: for (cur = last;
155: (pres = (HTTimer *) HTList_nextObject(cur)) != NULL && pres->expires < expires;
156: last = cur);
2.16 frystyk 157:
158: /*
159: ** If the expiration is 0 then we still register it but dispatch it immediately.
160: */
161: if (!millis) if (THD_TRACE) HTTrace("Timer....... Timeout is 0 - expires NOW\n");
162:
2.3 eric 163: timer->expires = expires;
2.1 frystyk 164: timer->cbf = cbf;
165: timer->param = param;
166: timer->millis = millis;
167: timer->relative = relative;
2.7 eric 168: SETME(timer);
2.3 eric 169:
170: /*
171: ** add to list if timer is new
172: */
2.7 eric 173: HTList_addObject(last, (void *)timer);
2.9 frystyk 174:
175: /*
176: ** Call any platform specific timer handler
177: */
178: if (SetPlatformTimer) SetPlatformTimer(timer);
179:
2.16 frystyk 180: /*
181: ** Check if the timer object has already expired
182: */
183: if (timer->expires <= now) {
184: int status;
185: if ((status = (*timer->cbf)(timer, timer->param, HTEvent_TIMEOUT)) != HT_OK) {
186: if (cur) HTList_quickRemoveElement(cur, last);
187: CLEARME(timer);
188: HT_FREE(timer);
189: return NULL;
190: }
191: }
192:
2.7 eric 193: CLEARME(timer);
2.1 frystyk 194: return timer;
195: }
196:
197:
2.7 eric 198: PUBLIC BOOL HTTimer_refresh (HTTimer * timer, ms_t now)
199: {
200: if (timer == NULL || timer->relative == NO)
201: return NO;
202: if (HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES) == NULL)
203: return NO;
204: return YES;
205: }
206:
2.1 frystyk 207: PUBLIC BOOL HTTimer_deleteAll (void)
208: {
2.3 eric 209: HTList * cur = Timers;
210: HTTimer * pres;
211: if (Timers) {
212: while ((pres = (HTTimer *) HTList_nextObject(cur))) {
2.9 frystyk 213:
214: /*
215: ** Call any platform specific timer handler
216: */
217: if (DeletePlatformTimer) DeletePlatformTimer(pres);
2.3 eric 218: HT_FREE(pres);
2.1 frystyk 219: }
2.3 eric 220: HTList_delete(Timers);
221: Timers = NULL;
2.1 frystyk 222: return YES;
223: }
224: return NO;
225: }
226:
227: /*
228: ** When a timer has expired, we dispatch the event handler and re-register the
229: ** timer with the next expiration time.
230: */
2.3 eric 231: PRIVATE int Timer_dispatch (HTList * cur, HTList * last, int now)
2.1 frystyk 232: {
2.3 eric 233: HTTimer * timer;
234: int ret;
2.17 ! frystyk 235: BOOL relative;
2.3 eric 236:
237: timer = (HTTimer *)HTList_objectOf(cur);
2.7 eric 238: if (timer == NULL) {
239: HTDebugBreak();
240: CLEARME(timer);
2.3 eric 241: return HT_ERROR;
2.7 eric 242: }
2.17 ! frystyk 243: relative = timer->relative;
! 244: if (relative)
2.1 frystyk 245: HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES);
2.3 eric 246: else
247: HTList_quickRemoveElement(cur, last);
2.1 frystyk 248: if (THD_TRACE) HTTrace("Timer....... Dispatch timer %p\n", timer);
2.7 eric 249: ret = (*timer->cbf) (timer, timer->param, HTEvent_TIMEOUT);
2.17 ! frystyk 250: if (!relative) {
! 251:
! 252: /*
! 253: ** Call any platform specific timer handler
! 254: */
! 255: if (DeletePlatformTimer) DeletePlatformTimer(timer);
! 256:
2.3 eric 257: HT_FREE(timer);
2.17 ! frystyk 258: }
2.3 eric 259: return ret;
260: }
261:
262: PUBLIC int HTTimer_dispatch (HTTimer * timer)
263: {
264: HTList * cur;
265: HTList * last = Timers;
266: ms_t now = HTGetTimeInMillis();
267:
268: cur = HTList_elementOf(Timers, (void *)timer, &last);
269: return Timer_dispatch(cur, last, now);
2.1 frystyk 270: }
271:
2.7 eric 272: PUBLIC int HTTimer_next (ms_t * pSoonest)
2.1 frystyk 273: {
2.17 ! frystyk 274: HTList * cur = Timers;
! 275: HTList * last = Timers;
2.7 eric 276: HTTimer * pres;
2.3 eric 277: ms_t now = HTGetTimeInMillis();
2.7 eric 278: int ret = HT_OK;
2.3 eric 279:
2.17 ! frystyk 280: #if 0
! 281: if (Timers == NULL) return HT_OK;
2.7 eric 282: /* The Timers list may be modified during a dispatch
283: ** so we have to build an intermediate list
284: */
285: head = last = HTList_new();
286: cur = Timers;
2.3 eric 287: while ((pres = (HTTimer *) HTList_nextObject(cur)) && pres->expires <= now) {
2.7 eric 288: HTList_addObject(last, (void *)pres);
289: last = HTList_nextObject(last);
290: }
291:
292: /*
293: ** Now dispatch the intermediate list
294: */
295: cur = last = head;
296: while ((pres = (HTTimer *) HTList_nextObject(cur)) && ret == HT_OK) {
297: ret = Timer_dispatch(cur, last, now);
2.3 eric 298: last = cur;
2.2 frystyk 299: }
2.17 ! frystyk 300: #else
! 301: /*
! 302: ** Dispatch all timers that have expired
! 303: */
! 304: while (Timers && (pres = (HTTimer *) HTList_nextObject(cur))) {
! 305: if (pres->expires <= now) {
! 306: if ((ret = Timer_dispatch(cur, last, now)) != HT_OK) break;
! 307: cur = last = Timers;
! 308: } else {
! 309: last = cur;
! 310: }
! 311: }
! 312: #endif
2.3 eric 313:
2.7 eric 314: if (pSoonest) {
315: /*
316: ** First element in Timers is the next to expire.
2.3 eric 317: */
2.8 frystyk 318: HTList * cur = Timers; /* for now */
319: pres = (HTTimer *) HTList_nextObject(cur);
2.7 eric 320: *pSoonest = pres ? pres->expires - now : 0;
2.1 frystyk 321: }
2.7 eric 322: return ret;
2.1 frystyk 323: }
2.12 eric 324:
2.13 frystyk 325: #ifdef WATCH_RECURSION
2.12 eric 326: extern void CheckSockEvent(HTTimer * timer, HTTimerCallback * cbf, void * param);
2.13 frystyk 327: PRIVATE void CheckTimers(void)
2.12 eric 328: {
329: HTList * cur = Timers;
330: HTTimer * pres;
331: while ((pres = (HTTimer *) HTList_nextObject(cur))) {
332: CheckSockEvent(pres, pres->cbf, pres->param);
333: }
334: }
2.13 frystyk 335: #endif
Webmaster