static void delayUntilNextTimerEvent(struct timeval *delay) { struct timeval now; TimerHandler *handler; handler = timerHandler; while (handler && IS_ZERO(handler->when)) handler = handler->next; if (!handler) { /* The return value of this function is only valid if there _are_ timers active. */ delay->tv_sec = 0; delay->tv_usec = 0; return; } rightNow(&now); if (IS_AFTER(now, handler->when)) { delay->tv_sec = 0; delay->tv_usec = 0; } else { delay->tv_sec = handler->when.tv_sec - now.tv_sec; delay->tv_usec = handler->when.tv_usec - now.tv_usec; if (delay->tv_usec < 0) { delay->tv_usec += 1000000; delay->tv_sec--; } } }
static void enqueueTimerHandler(TimerHandler *handler) { TimerHandler *tmp; /* insert callback in queue, sorted by time left */ if (!timerHandler || !IS_AFTER(handler->when, timerHandler->when)) { /* first in the queue */ handler->next = timerHandler; timerHandler = handler; } else { tmp = timerHandler; while (tmp->next && IS_AFTER(handler->when, tmp->next->when)) { tmp = tmp->next; } handler->next = tmp->next; tmp->next = handler; } }
static void AdjustTimes ( XtAppContext app, Boolean block, unsigned long* howlong, Boolean ignoreTimers, wait_times_ptr_t wt) { if (app->timerQueue != NULL && !ignoreTimers && block) { if (IS_AFTER (wt->cur_time, app->timerQueue->te_timer_value)) { TIMEDELTA (wt->wait_time, app->timerQueue->te_timer_value, wt->cur_time); if (howlong == NULL || IS_AFTER (wt->wait_time, wt->max_wait_time)) #ifndef USE_POLL wt->wait_time_ptr = &wt->wait_time; else wt->wait_time_ptr = &wt->max_wait_time; } else wt->wait_time_ptr = &zero_time; } #else wt->poll_wait = wt->wait_time.tv_sec * 1000 + wt->wait_time.tv_usec / 1000; else
void GLUTAPIENTRY glutTimerFunc(unsigned int interval, GLUTtimerCB timerFunc, int value) { GLUTtimer *timer, *other; GLUTtimer **prevptr; #ifdef OLD_VMS struct timeval6 now; #else struct timeval now; #endif if (!timerFunc) return; if (freeTimerList) { timer = freeTimerList; freeTimerList = timer->next; } else { timer = (GLUTtimer *) malloc(sizeof(GLUTtimer)); if (!timer) __glutFatalError("out of memory."); } timer->func = timerFunc; #if defined(__vms) && ( __VMS_VER < 70000000 ) /* VMS time is expressed in units of 100 ns */ timer->timeout.val = interval * TICKS_PER_MILLISECOND; #else timer->timeout.tv_sec = (int) interval / 1000; timer->timeout.tv_usec = (int) (interval % 1000) * 1000; #endif timer->value = value; timer->next = NULL; GETTIMEOFDAY(&now); ADD_TIME(timer->timeout, timer->timeout, now); prevptr = &__glutTimerList; other = *prevptr; while (other && IS_AFTER(other->timeout, timer->timeout)) { prevptr = &other->next; other = *prevptr; } timer->next = other; #ifdef SUPPORT_FORTRAN __glutNewTimer = timer; /* for Fortran binding! */ #endif *prevptr = timer; }
void W_CheckTimerHandlers(void) { TimerHandler *handler; struct timeval now; if (!timerHandler) { W_FlushASAPNotificationQueue(); return; } rightNow(&now); handler = timerHandler; while (handler && IS_AFTER(now, handler->when)) { if (!IS_ZERO(handler->when)) { SET_ZERO(handler->when); (*handler->callback)(handler->clientData); } handler = handler->next; } while (timerHandler && IS_ZERO(timerHandler->when)) { handler = timerHandler; timerHandler = timerHandler->next; if (handler->nextDelay > 0) { handler->when = now; addmillisecs(&handler->when, handler->nextDelay); enqueueTimerHandler(handler); } else { wfree(handler); } } W_FlushASAPNotificationQueue(); }
static void waitForSomething(void) { #if defined(__vms) && ( __VMS_VER < 70000000 ) static struct timeval6 zerotime = {0}; unsigned int timer_efn; #define timer_id 'glut' /* random :-) number */ unsigned int wait_mask; #else static struct timeval zerotime = {0, 0}; #if !defined(_WIN32) fd_set fds; #endif #endif #ifdef OLD_VMS struct timeval6 now, timeout, waittime; #else struct timeval now, timeout, waittime; #endif #if !defined(_WIN32) int rc; #endif /* Flush X protocol since XPending does not do this implicitly. */ XFlush(__glutDisplay); if (XPending(__glutDisplay)) { /* It is possible (but quite rare) that XFlush may have needed to wait for a writable X connection file descriptor, and in the process, may have had to read off X protocol from the file descriptor. If XPending is true, this case occured and we should avoid waiting in select since X protocol buffered within Xlib is due to be processed and potentially no more X protocol is on the file descriptor, so we would risk waiting improperly in select. */ goto immediatelyHandleXinput; } #if defined(__vms) && ( __VMS_VER < 70000000 ) timeout = __glutTimerList->timeout; GETTIMEOFDAY(&now); wait_mask = 1 << (__glutConnectionFD & 31); if (IS_AFTER(now, timeout)) { /* We need an event flag for the timer. */ /* XXX The `right' way to do this is to use LIB$GET_EF, but since it needs to be in the same cluster as the EFN for the display, we will have hack it. */ timer_efn = __glutConnectionFD - 1; if ((timer_efn / 32) != (__glutConnectionFD / 32)) { timer_efn = __glutConnectionFD + 1; } rc = SYS$CLREF(timer_efn); rc = SYS$SETIMR(timer_efn, &timeout, NULL, timer_id, 0); wait_mask |= 1 << (timer_efn & 31); } else { timer_efn = 0; } rc = SYS$WFLOR(__glutConnectionFD, wait_mask); if (timer_efn != 0 && SYS$CLREF(timer_efn) == SS$_WASCLR) { rc = SYS$CANTIM(timer_id, PSL$C_USER); } /* XXX There does not seem to be checking of "rc" in the code above. Can any of the SYS$ routines above fail? */ #else /* not vms6.2 or lower */ #if !defined(_WIN32) FD_ZERO(&fds); FD_SET(__glutConnectionFD, &fds); #endif timeout = __glutTimerList->timeout; GETTIMEOFDAY(&now); if (IS_AFTER(now, timeout)) { TIMEDELTA(waittime, timeout, now); } else { waittime = zerotime; } #if !defined(_WIN32) rc = select(__glutConnectionFD + 1, &fds, NULL, NULL, &waittime); if (rc < 0 && errno != EINTR) __glutFatalError("select error."); #else MsgWaitForMultipleObjects(0, NULL, FALSE, waittime.tv_sec*1000 + waittime.tv_usec/1000, QS_ALLINPUT); #endif #endif /* not vms6.2 or lower */ /* Without considering the cause of select unblocking, check for pending X events and handle any timeouts (by calling processEventsAndTimeouts). We always look for X events even if select returned with 0 (indicating a timeout); otherwise we risk starving X event processing by continous timeouts. */ if (XPending(__glutDisplay)) { immediatelyHandleXinput: processEventsAndTimeouts(); } else { if (__glutTimerList) handleTimeouts(); } }
/* Wait for either Timer, Alternate Input, or an X Event to arrive */ int XETrapWaitForSomething(XtAppContext app) { #ifndef vms return(_XtWaitForSomething(app, FALSE, FALSE, FALSE, FALSE, TRUE #ifdef XTHREADS , FALSE #endif /* XTHREADS */ , 0L)); #else /* vms */ #define IS_AFTER(t1,t2) (((t2).high > (t1).high) \ ||(((t2).high == (t1).high)&& ((t2).low > (t1).low))) long retval = 0L; TimerEventRec *te_ptr; vms_time cur_time,result_time; int status = 0; long quotient, remainder = 0; int d; if (app->timerQueue!= NULL) { /* check timeout queue */ cur_time.low = cur_time.high = result_time.low = result_time.high = 0; te_ptr = app->timerQueue; sys$gettim(&cur_time); if ((IS_AFTER(app->timerQueue->te_timer_value, cur_time)) && (app->timerQueue->te_proc != 0)) { /* it's fired! return! */ return(0); } /* Jump through hoops to get the time specified in the queue into * milliseconds */ status = lib$sub_times (&(te_ptr->te_timer_value.low), &cur_time, &result_time); /* * See if this timer has expired. A timer is considered expired * if it's value in the past (the NEGTIM case) or if there is * less than one integral milli second before it would go off. */ if (status == LIB$_NEGTIM || (result_time.high == -1 && result_time.low > -10000)) { /* We've got a timer and it's ready to fire! */ return(0); } else if ((status & 1) == 1) { lib$ediv (&(10000), &result_time, "ient, &remainder); quotient *= -1; /* flip the sign bit */ return(XMultiplexInput(app->count, &(app->list[0L]), app->Input_EF_Mask, quotient, 0L, &retval)); } else { status = -1; } } return((status == -1 ? -1 : XMultiplexInput(app->count, &(app->list[0L]), app->Input_EF_Mask, 0L, 0L, &retval))); #endif /* vms */ }