jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id) { Jim_TimeEvent *te; Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); if (id >= eventLoop->timeEventNextId) { return -2; /* wrong event ID */ } te = Jim_RemoveTimeHandler(eventLoop, id); if (te) { jim_wide remain; long cur_sec, cur_ms; JimGetTime(&cur_sec, &cur_ms); remain = (te->when_sec - cur_sec) * 1000; remain += (te->when_ms - cur_ms); remain = (remain < 0) ? 0 : remain; Jim_FreeTimeHandler(interp, te); return remain; } return -1; /* NO event with the specified ID found */ }
jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id) { Jim_TimeEvent *te; Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); if (id > eventLoop->timeEventNextId) { return -2; /* wrong event ID */ } te = Jim_RemoveTimeHandler(eventLoop, id); if (te) { jim_wide remain; remain = te->when - JimGetTimeUsec(eventLoop); remain = (remain < 0) ? 0 : remain; Jim_FreeTimeHandler(interp, te); return remain; } return -1; /* NO event with the specified ID found */ }
/* Process every pending time event, then every pending file event * (that may be registered by time event callbacks just processed). * The behaviour depends upon the setting of flags: * * If flags is 0, the function does nothing and returns. * if flags has JIM_ALL_EVENTS set, all event types are processed. * if flags has JIM_FILE_EVENTS set, file events are processed. * if flags has JIM_TIME_EVENTS set, time events are processed. * if flags has JIM_DONT_WAIT set, the function returns as soon as all * the events that are possible to process without waiting are processed. * * Returns the number of events processed or -1 if * there are no matching handlers, or -2 on error. */ int Jim_ProcessEvents(Jim_Interp *interp, int flags) { jim_wide sleep_us = -1; int processed = 0; Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); Jim_FileEvent *fe = eventLoop->fileEventHead; Jim_TimeEvent *te; jim_wide maxId; if ((flags & JIM_FILE_EVENTS) == 0 || fe == NULL) { /* No file events */ if ((flags & JIM_TIME_EVENTS) == 0 || eventLoop->timeEventHead == NULL) { /* No time events */ return -1; } } /* Note that we want call select() even if there are no * file events to process as long as we want to process time * events, in order to sleep until the next time event is ready * to fire. */ if (flags & JIM_DONT_WAIT) { /* Wait no time */ sleep_us = 0; } else if (flags & JIM_TIME_EVENTS) { /* The nearest timer is always at the head of the list */ if (eventLoop->timeEventHead) { Jim_TimeEvent *shortest = eventLoop->timeEventHead; /* Calculate the time missing for the nearest * timer to fire. */ sleep_us = shortest->when - JimGetTimeUsec(eventLoop); if (sleep_us < 0) { sleep_us = 0; } } else { /* Wait forever */ sleep_us = -1; } } #ifdef HAVE_SELECT if (flags & JIM_FILE_EVENTS) { int retval; struct timeval tv, *tvp = NULL; fd_set rfds, wfds, efds; int maxfd = -1; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); /* Check file events */ while (fe != NULL) { if (fe->mask & JIM_EVENT_READABLE) FD_SET(fe->fd, &rfds); if (fe->mask & JIM_EVENT_WRITABLE) FD_SET(fe->fd, &wfds); if (fe->mask & JIM_EVENT_EXCEPTION) FD_SET(fe->fd, &efds); if (maxfd < fe->fd) maxfd = fe->fd; fe = fe->next; } if (sleep_us >= 0) { tvp = &tv; tvp->tv_sec = sleep_us / 1000000; tvp->tv_usec = sleep_us % 1000000; } retval = select(maxfd + 1, &rfds, &wfds, &efds, tvp); if (retval < 0) { if (errno == EINVAL) { /* This can happen on mingw32 if a non-socket filehandle is passed */ Jim_SetResultString(interp, "non-waitable filehandle", -1); return -2; } } else if (retval > 0) { fe = eventLoop->fileEventHead; while (fe != NULL) { int mask = 0; int fd = fe->fd; if ((fe->mask & JIM_EVENT_READABLE) && FD_ISSET(fd, &rfds)) mask |= JIM_EVENT_READABLE; if (fe->mask & JIM_EVENT_WRITABLE && FD_ISSET(fd, &wfds)) mask |= JIM_EVENT_WRITABLE; if (fe->mask & JIM_EVENT_EXCEPTION && FD_ISSET(fd, &efds)) mask |= JIM_EVENT_EXCEPTION; if (mask) { int ret = fe->fileProc(interp, fe->clientData, mask); if (ret != JIM_OK && ret != JIM_RETURN) { /* Remove the element on handler error */ Jim_DeleteFileHandler(interp, fd, mask); /* At this point fe is no longer valid - it will be assigned below */ } processed++; /* After an event is processed our file event list * may no longer be the same, so what we do * is to clear the bit for this file descriptor and * restart again from the head. */ FD_CLR(fd, &rfds); FD_CLR(fd, &wfds); FD_CLR(fd, &efds); fe = eventLoop->fileEventHead; } else { fe = fe->next; } } } } #else if (sleep_us > 0) { usleep(sleep_us); } #endif /* Check time events */ te = eventLoop->timeEventHead; maxId = eventLoop->timeEventNextId; while (te) { jim_wide id; if (te->id > maxId) { te = te->next; continue; } if (JimGetTimeUsec(eventLoop) >= te->when) { id = te->id; /* Remove from the list before executing */ Jim_RemoveTimeHandler(eventLoop, id); te->timeProc(interp, te->clientData); /* After an event is processed our time event list may * no longer be the same, so we restart from head. * Still we make sure to don't process events registered * by event handlers itself in order to don't loop forever * even in case an [after 0] that continuously register * itself. To do so we saved the max ID we want to handle. */ Jim_FreeTimeHandler(interp, te); te = eventLoop->timeEventHead; processed++; } else { te = te->next; } } return processed; }