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