📄 event.c
字号:
*/ FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&errfds); maxfd = 0; see_event = (wait_eh == (event_handle_t *)NULL); /* * Run through each event handle and setup the events. * We save our next pointer early in case we GC some dead * events. */ for (eh = eventq_first(eventq); eh != NULL; eh = nexteh) { nexteh = eventq_next(eh); switch (eh->type) { /* * Read fds just get set into the select bitmask */ case EV_READFD: FD_SET((int)eh->data, &readfds); FD_SET((int)eh->data, &errfds); maxfd = max(maxfd, (int)eh->data); see_event |= (eh == wait_eh); break; /* * Likewise with write fds */ case EV_WRITEFD: FD_SET((int)eh->data, &writefds); FD_SET((int)eh->data, &errfds); maxfd = max(maxfd, (int)eh->data); see_event |= (eh == wait_eh); break; /* * Only set signals that aren't already set to avoid unnecessary * syscall overhead. */ case EV_SIG: se = &sigtable[eh->data]; see_event |= (eh == wait_eh); if (se->handle == eh) break; /* no previous handle */ assert(se->handle == NULL); se->handle = eh; se->score = 0; /*@ignore@*/ se->oldhandler = signal((int)eh->data, signal_handler); /*@end@*/ break; /* * Compute the timeout for this select */ case EV_TIME: /* if we're not supposed to block, then leave it at 0 */ if (dontblock) break; if (eh->lastfired == -1) eh->lastfired = curtime; interval = (long)(eh->data - (curtime - eh->lastfired)); if (interval < 0) interval = 0; if (tvptr != NULL) timeout.tv_sec = min(timeout.tv_sec, interval); else { /* this is the first timeout */ tvptr = &timeout; timeout.tv_sec = interval; } see_event |= (eh == wait_eh); break; /* * Wait events are processed immediately by event_wakeup() */ case EV_WAIT: see_event |= (eh == wait_eh); break; /* * Prune dead events */ case EV_DEAD: eventq_remove(eh); puthandle(eh); break; default: assert(0); break; } } if(!see_event) { assert(--entry == 0); return 0; } /* * Let 'er rip */ event_debug(1, _("event: select: dontblock=%d, maxfd=%d, timeout=%ld\n"), dontblock, maxfd, tvptr != NULL ? timeout.tv_sec : -1); rc = select(maxfd + 1, &readfds, &writefds, &errfds, tvptr); event_debug(1, _("event: select returns %d\n"), rc); /* * Select errors can mean many things. Interrupted events should * not be fatal, since they could be delivered signals which still * need to have their events fired. */ if (rc < 0) { if (errno != EINTR) { if (++ntries > 5) { error(_("select failed: %s"), strerror(errno)); /*NOTREACHED*/ } continue; } /* proceed if errno == EINTR, we may have caught a signal */ /* contents cannot be trusted */ FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&errfds); } /* * Grab the current time again for use in timed events. */ curtime = time(NULL); /* * We need to copy the errfds into werrfds, so file descriptors * that are being polled for both reading and writing have * both of their poll events 'see' the error. */ memcpy(&werrfds, &errfds, SIZEOF(werrfds)); /* * Now run through the events and fire the ones that are ready. * Don't handle file descriptor events if the select failed. */ for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) { switch (eh->type) { /* * Read fds: just fire the event if set in the bitmask */ case EV_READFD: if (FD_ISSET((int)eh->data, &readfds) || FD_ISSET((int)eh->data, &errfds)) { FD_CLR((int)eh->data, &readfds); FD_CLR((int)eh->data, &errfds); fire(eh); if(eh == wait_eh) event_wait_fired = 1; } break; /* * Write fds: same as Read fds */ case EV_WRITEFD: if (FD_ISSET((int)eh->data, &writefds) || FD_ISSET((int)eh->data, &werrfds)) { FD_CLR((int)eh->data, &writefds); FD_CLR((int)eh->data, &werrfds); fire(eh); if(eh == wait_eh) event_wait_fired = 1; } break; /* * Signal events: check the score for fires, and run the * event if we got one. */ case EV_SIG: se = &sigtable[eh->data]; if (se->score > 0) { assert(se->handle == eh); se->score = 0; fire(eh); if(eh == wait_eh) event_wait_fired = 1; } break; /* * Timed events: check the interval elapsed since last fired, * and set it off if greater or equal to requested interval. */ case EV_TIME: if (eh->lastfired == -1) eh->lastfired = curtime; if ((curtime - eh->lastfired) >= (time_t)eh->data) { eh->lastfired = curtime; fire(eh); if(eh == wait_eh) event_wait_fired = 1; } break; /* * Wait events are handled immediately by event_wakeup() * Dead events are handled by the pre-select loop. */ case EV_WAIT: case EV_DEAD: break; default: assert(0); break; } } } while (!dontblock && eventq.qlength > 0 && event_wait_fired == 0); assert(--entry == 0); return (event_wait_fired == 1);}/* * Generic signal handler. Used to count caught signals for the event * loop. */static voidsignal_handler( int signo){ assert((signo >= 0) && ((size_t)signo < (size_t)(sizeof(sigtable) / sizeof(sigtable[0])))); sigtable[signo].score++;}/* * Return a new handle. Take from the handle cache if not empty. Otherwise, * alloc a new one. */static event_handle_t *gethandle(void){ event_handle_t *eh; if ((eh = eventq_first(cache)) != NULL) { assert(cache.qlength > 0); eventq_remove(eh); cache.qlength--; return (eh); } assert(cache.qlength == 0); return (alloc(SIZEOF(*eh)));}/* * Free a handle. If there's space in the handle cache, put it there. * Otherwise, free it. */static voidputhandle( event_handle_t *eh){ if (cache.qlength > CACHEDEPTH) { amfree(eh); return; } eventq_add(cache, eh); cache.qlength++;}/* * Convert an event type into a string */static const char *event_type2str( event_type_t type){ static const struct { event_type_t type; const char name[12]; } event_types[] = {#define X(s) { s, stringize(s) } X(EV_READFD), X(EV_WRITEFD), X(EV_SIG), X(EV_TIME), X(EV_WAIT), X(EV_DEAD),#undef X }; size_t i; for (i = 0; i < (size_t)(sizeof(event_types) / sizeof(event_types[0])); i++) if (type == event_types[i].type) return (event_types[i].name); return (_("BOGUS EVENT TYPE"));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -