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