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