Annotation of libwww/Library/src/HTTimer.c, revision 2.7
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.7 ! eric 6: ** @(#) $Id: HTTimer.c,v 2.6 1996年12月07日 19:14:36 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.7 ! eric 36: #if 1 /* WATCH_RECURSION */
! 37:
! 38: PRIVATE HTTimer * InTimer = NULL;
! 39: #define CHECKME(timer) if (InTimer != NULL) HTDebugBreak(); InTimer = timer;
! 40: #define CLEARME(timer) if (InTimer != timer) HTDebugBreak(); InTimer = NULL;
! 41: #define SETME(timer) InTimer = timer;
! 42:
! 43: #else /* WATCH_RECURSION */
! 44:
! 45: #define CHECKME(timer)
! 46: #define CLEARME(timer)
! 47: #define SETME(timer)
! 48:
! 49: #endif /* !WATCH_RECURSION */
2.1 frystyk 50: /* ------------------------------------------------------------------------- */
51:
2.4 eric 52: #ifdef WWW_WIN_ASYNC
53:
54: #define SET_PLATFORM_TIMER(timer) Timer_setWindowsTimer(timer)
55: #define DELETE_PLATFORM_TIMER(timer) Timer_deleteWindowsTimer(timer)
56:
57: PRIVATE int Timer_setWindowsTimer(HTTimer * timer)
58: {
59: HWND hwnd;
60: UINT id;
2.5 eric 61: hwnd = HTEventList_getWinHandle(&id);
2.4 eric 62: return SetTimer(hwnd, (UINT)timer, (UINT)timer->millis, NULL) != 0;
63: }
64:
65: PRIVATE int Timer_deleteWindowsTimer(HTTimer * timer)
66: {
67: HWND hwnd;
68: UINT id;
2.5 eric 69: hwnd = HTEventList_getWinHandle(&id);
2.4 eric 70: return KillTimer(hwnd, (UINT)timer) != 0;
71: }
72:
73: #else /* WWW_WIN_ASYNC */
74:
75: #define SET_PLATFORM_TIMER(timer)
76: #define DELETE_PLATFORM_TIMER(timer)
77:
78: #endif /* !WWW_WIN_ASYNC */
79:
2.1 frystyk 80: PUBLIC BOOL HTTimer_delete (HTTimer * timer)
81: {
2.3 eric 82: HTList * last;
83: HTList * cur;
2.7 ! eric 84: CHECKME(timer);
! 85: if ((cur = HTList_elementOf(Timers, (void *)timer, &last)) == NULL) {
! 86: HTDebugBreak();
! 87: CLEARME(timer);
2.3 eric 88: return NO;
2.7 ! eric 89: }
2.3 eric 90: HTList_quickRemoveElement(cur, last);
2.4 eric 91: DELETE_PLATFORM_TIMER(timer);
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.4 eric 165: SET_PLATFORM_TIMER(timer);
2.7 ! eric 166: CLEARME(timer);
2.1 frystyk 167: return timer;
168: }
169:
170:
2.7 ! eric 171: PUBLIC BOOL HTTimer_refresh (HTTimer * timer, ms_t now)
! 172: {
! 173: if (timer == NULL || timer->relative == NO)
! 174: return NO;
! 175: if (HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES) == NULL)
! 176: return NO;
! 177: return YES;
! 178: }
! 179:
2.1 frystyk 180: PUBLIC BOOL HTTimer_deleteAll (void)
181: {
2.3 eric 182: HTList * cur = Timers;
183: HTTimer * pres;
184: if (Timers) {
185: while ((pres = (HTTimer *) HTList_nextObject(cur))) {
2.4 eric 186: DELETE_PLATFORM_TIMER(pres);
2.3 eric 187: HT_FREE(pres);
2.1 frystyk 188: }
2.3 eric 189: HTList_delete(Timers);
190: Timers = NULL;
2.1 frystyk 191: return YES;
192: }
193: return NO;
194: }
195:
196: /*
197: ** When a timer has expired, we dispatch the event handler and re-register the
198: ** timer with the next expiration time.
199: */
2.3 eric 200: PRIVATE int Timer_dispatch (HTList * cur, HTList * last, int now)
2.1 frystyk 201: {
2.3 eric 202: HTTimer * timer;
203: int ret;
204:
205: timer = (HTTimer *)HTList_objectOf(cur);
2.7 ! eric 206: if (timer == NULL) {
! 207: HTDebugBreak();
! 208: CLEARME(timer);
2.3 eric 209: return HT_ERROR;
2.7 ! eric 210: }
2.1 frystyk 211: if (timer->relative)
212: HTTimer_new(timer, timer->cbf, timer->param, timer->millis, YES);
2.3 eric 213: else
214: HTList_quickRemoveElement(cur, last);
2.1 frystyk 215: if (THD_TRACE) HTTrace("Timer....... Dispatch timer %p\n", timer);
2.7 ! eric 216: /* CHECKME(timer); all entries to this function are now re-entry save */
! 217: ret = (*timer->cbf) (timer, timer->param, HTEvent_TIMEOUT);
! 218: /* CLEARME(timer); */
2.3 eric 219: if (!timer->relative)
220: HT_FREE(timer);
221: return ret;
222: }
223:
224: PUBLIC int HTTimer_dispatch (HTTimer * timer)
225: {
226: HTList * cur;
227: HTList * last = Timers;
228: ms_t now = HTGetTimeInMillis();
229:
230: cur = HTList_elementOf(Timers, (void *)timer, &last);
231: return Timer_dispatch(cur, last, now);
2.1 frystyk 232: }
233:
2.7 ! eric 234: PUBLIC int HTTimer_next (ms_t * pSoonest)
2.1 frystyk 235: {
2.7 ! eric 236: HTList * cur;
! 237: HTList * last;
! 238: HTTimer * pres;
2.3 eric 239: ms_t now = HTGetTimeInMillis();
2.7 ! eric 240: int ret = HT_OK;
! 241: HTList * head;
2.3 eric 242:
243: if (Timers == NULL)
2.7 ! eric 244: return HT_OK;
2.3 eric 245:
2.7 ! eric 246: /* The Timers list may be modified during a dispatch
! 247: ** so we have to build an intermediate list
! 248: */
! 249: head = last = HTList_new();
! 250: cur = Timers;
2.3 eric 251: while ((pres = (HTTimer *) HTList_nextObject(cur)) && pres->expires <= now) {
2.7 ! eric 252: HTList_addObject(last, (void *)pres);
! 253: last = HTList_nextObject(last);
! 254: }
! 255:
! 256: /*
! 257: ** Now dispatch the intermediate list
! 258: */
! 259: cur = last = head;
! 260: while ((pres = (HTTimer *) HTList_nextObject(cur)) && ret == HT_OK) {
! 261: ret = Timer_dispatch(cur, last, now);
2.3 eric 262: last = cur;
2.2 frystyk 263: }
2.3 eric 264:
2.7 ! eric 265: if (pSoonest) {
! 266: /*
! 267: ** First element in Timers is the next to expire.
2.3 eric 268: */
2.7 ! eric 269: pres = (HTTimer *) HTList_nextObject(Timers);
! 270: *pSoonest = pres ? pres->expires - now : 0;
2.1 frystyk 271: }
2.7 ! eric 272: HTList_delete(head);
! 273: return ret;
2.1 frystyk 274: }
Webmaster