📄 eventlib.c
字号:
ctx->fdCount = 0; } /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ goto again;}intevDispatch(evContext opaqueCtx, evEvent opaqueEv) { evContext_p *ctx = opaqueCtx.opaque; evEvent_p *ev = opaqueEv.opaque;#ifdef EVENTLIB_TIME_CHECKS void *func; struct timespec start_time; struct timespec interval;#endif#ifdef EVENTLIB_TIME_CHECKS if (ctx->debug > 0) start_time = evNowTime();#endif ctx->cur = ev; switch (ev->type) { case Accept: { evAccept *this = ev->u.accept.this; evPrintf(ctx, 5, "Dispatch.Accept: fd %d -> %d, func %p, uap %p\n", this->conn->fd, this->fd, this->conn->func, this->conn->uap); errno = this->ioErrno; (this->conn->func)(opaqueCtx, this->conn->uap, this->fd, &this->la, this->lalen, &this->ra, this->ralen);#ifdef EVENTLIB_TIME_CHECKS func = this->conn->func;#endif break; } case File: { evFile *this = ev->u.file.this; int eventmask = ev->u.file.eventmask; evPrintf(ctx, 5, "Dispatch.File: fd %d, mask 0x%x, func %p, uap %p\n", this->fd, this->eventmask, this->func, this->uap); (this->func)(opaqueCtx, this->uap, this->fd, eventmask);#ifdef EVENTLIB_TIME_CHECKS func = this->func;#endif break; } case Stream: { evStream *this = ev->u.stream.this; evPrintf(ctx, 5, "Dispatch.Stream: fd %d, func %p, uap %p\n", this->fd, this->func, this->uap); errno = this->ioErrno; (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone);#ifdef EVENTLIB_TIME_CHECKS func = this->func;#endif break; } case Timer: { evTimer *this = ev->u.timer.this; evPrintf(ctx, 5, "Dispatch.Timer: func %p, uap %p\n", this->func, this->uap); (this->func)(opaqueCtx, this->uap, this->due, this->inter);#ifdef EVENTLIB_TIME_CHECKS func = this->func;#endif break; } case Wait: { evWait *this = ev->u.wait.this; evPrintf(ctx, 5, "Dispatch.Wait: tag %p, func %p, uap %p\n", this->tag, this->func, this->uap); (this->func)(opaqueCtx, this->uap, this->tag);#ifdef EVENTLIB_TIME_CHECKS func = this->func;#endif break; } case Null: { /* No work. */#ifdef EVENTLIB_TIME_CHECKS func = NULL;#endif break; } default: { abort(); } }#ifdef EVENTLIB_TIME_CHECKS if (ctx->debug > 0) { interval = evSubTime(evNowTime(), start_time); /* * Complain if it took longer than 50 milliseconds. * * We call getuid() to make an easy to find mark in a kernel * trace. */ if (interval.tv_sec > 0 || interval.tv_nsec > 50000000) evPrintf(ctx, 1, "dispatch interval %u.%09u uid %d type %d func %p\n", interval.tv_sec, interval.tv_nsec, getuid(), ev->type, func); }#endif ctx->cur = NULL; evDrop(opaqueCtx, opaqueEv); return (0);}voidevDrop(evContext opaqueCtx, evEvent opaqueEv) { evContext_p *ctx = opaqueCtx.opaque; evEvent_p *ev = opaqueEv.opaque; switch (ev->type) { case Accept: { FREE(ev->u.accept.this); break; } case File: { /* No work. */ break; } case Stream: { evStreamID id; id.opaque = ev->u.stream.this; (void) evCancelRW(opaqueCtx, id); break; } case Timer: { evTimer *this = ev->u.timer.this; evTimerID opaque; /* Check to see whether the user func cleared the timer. */ if (heap_element(ctx->timers, this->index) != this) { evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n"); break; } /* * Timer is still there. Delete it if it has expired, * otherwise set it according to its next interval. */ if (this->inter.tv_sec == (time_t)0 && this->inter.tv_nsec == 0L) { opaque.opaque = this; (void) evClearTimer(opaqueCtx, opaque); } else { opaque.opaque = this; (void) evResetTimer(opaqueCtx, opaque, this->func, this->uap, evAddTime((this->mode & EV_TMR_RATE) ? this->due : ctx->lastEventTime, this->inter), this->inter); } break; } case Wait: { FREE(ev->u.wait.this); break; } case Null: { /* No work. */ break; } default: { abort(); } } FREE(ev);}intevMainLoop(evContext opaqueCtx) { evEvent event; int x; while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) if ((x = evDispatch(opaqueCtx, event)) < 0) break; return (x);}intevHighestFD(evContext opaqueCtx) { evContext_p *ctx = opaqueCtx.opaque; return (ctx->highestFD);}voidevPrintf(const evContext_p *ctx, int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (ctx->output != NULL && ctx->debug >= level) { vfprintf(ctx->output, fmt, ap); fflush(ctx->output); } va_end(ap);}intevSetOption(evContext *opaqueCtx, const char *option, int value) { /* evContext_p *ctx = opaqueCtx->opaque; */ UNUSED(opaqueCtx); UNUSED(value);#ifndef CLOCK_MONOTONIC UNUSED(option);#endif #ifdef CLOCK_MONOTONIC if (strcmp(option, "monotime") == 0) { if (opaqueCtx != NULL) errno = EINVAL; if (value == 0 || value == 1) { __evOptMonoTime = value; return (0); } else { errno = EINVAL; return (-1); } } #endif errno = ENOENT; return (-1);}intevGetOption(evContext *opaqueCtx, const char *option, int *value) { /* evContext_p *ctx = opaqueCtx->opaque; */ UNUSED(opaqueCtx);#ifndef CLOCK_MONOTONIC UNUSED(value); UNUSED(option);#endif #ifdef CLOCK_MONOTONIC if (strcmp(option, "monotime") == 0) { if (opaqueCtx != NULL) errno = EINVAL; *value = __evOptMonoTime; return (0); }#endif errno = ENOENT; return (-1);}#if defined(NEED_PSELECT) || defined(USE_POLL)/* XXX needs to move to the porting library. */static intpselect(int nfds, void *rfds, void *wfds, void *efds, struct timespec *tsp, const sigset_t *sigmask){ struct timeval tv, *tvp; sigset_t sigs; int n;#ifdef USE_POLL int polltimeout = INFTIM; evContext_p *ctx; struct pollfd *fds; nfds_t pnfds; UNUSED(nfds);#endif /* USE_POLL */ if (tsp) { tvp = &tv; tv = evTimeVal(*tsp);#ifdef USE_POLL polltimeout = 1000 * tv.tv_sec + tv.tv_usec / 1000;#endif /* USE_POLL */ } else tvp = NULL; if (sigmask) sigprocmask(SIG_SETMASK, sigmask, &sigs);#ifndef USE_POLL n = select(nfds, rfds, wfds, efds, tvp);#else /* * rfds, wfds, and efds should all be from the same evContext_p, * so any of them will do. If they're all NULL, the caller is * presumably calling us to block. */ if (rfds != NULL) ctx = ((__evEmulMask *)rfds)->ctx; else if (wfds != NULL) ctx = ((__evEmulMask *)wfds)->ctx; else if (efds != NULL) ctx = ((__evEmulMask *)efds)->ctx; else ctx = NULL; if (ctx != NULL && ctx->fdMax != -1) { fds = &(ctx->pollfds[ctx->firstfd]); pnfds = ctx->fdMax - ctx->firstfd + 1; } else { fds = NULL; pnfds = 0; } n = poll(fds, pnfds, polltimeout); /* * pselect() should return the total number of events on the file * desriptors, not just the count of fd:s with activity. Hence, * traverse the pollfds array and count the events. */ if (n > 0) { int i, e; for (e = 0, i = ctx->firstfd; i <= ctx->fdMax; i++) { if (ctx->pollfds[i].fd < 0) continue; if (FD_ISSET(i, &ctx->rdLast)) e++; if (FD_ISSET(i, &ctx->wrLast)) e++; if (FD_ISSET(i, &ctx->exLast)) e++; } n = e; }#endif /* USE_POLL */ if (sigmask) sigprocmask(SIG_SETMASK, &sigs, NULL); if (tsp) *tsp = evTimeSpec(tv); return (n);}#endif#ifdef USE_POLLintevPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd) { int i, maxnfds; void *pollfds, *fdTable; if (fd < ctx->maxnfds) return (0); /* Don't allow ridiculously small values for pollfd_chunk_size */ if (pollfd_chunk_size < 20) pollfd_chunk_size = 20; maxnfds = (1 + (fd/pollfd_chunk_size)) * pollfd_chunk_size; pollfds = realloc(ctx->pollfds, maxnfds * sizeof(*ctx->pollfds)); if (pollfds != NULL) ctx->pollfds = pollfds; fdTable = realloc(ctx->fdTable, maxnfds * sizeof(*ctx->fdTable)); if (fdTable != NULL) ctx->fdTable = fdTable; if (pollfds == NULL || fdTable == NULL) { evPrintf(ctx, 2, "pollfd() realloc (%ld) failed\n", (long)maxnfds*sizeof(struct pollfd)); return (-1); } for (i = ctx->maxnfds; i < maxnfds; i++) { ctx->pollfds[i].fd = -1; ctx->pollfds[i].events = 0; ctx->fdTable[i] = 0; } ctx->maxnfds = maxnfds; return (0);} /* Find the appropriate 'events' or 'revents' field in the pollfds array */short *__fd_eventfield(int fd, __evEmulMask *maskp) { evContext_p *ctx = (evContext_p *)maskp->ctx; if (!maskp->result || maskp->type == EV_WASNONBLOCKING) return (&(ctx->pollfds[fd].events)); else return (&(ctx->pollfds[fd].revents));} /* Translate to poll(2) event */short__poll_event(__evEmulMask *maskp) { switch ((maskp)->type) { case EV_READ: return (POLLRDNORM); case EV_WRITE: return (POLLWRNORM); case EV_EXCEPT: return (POLLRDBAND | POLLPRI | POLLWRBAND); case EV_WASNONBLOCKING: return (POLLHUP); default: return (0); }} /* * Clear the events corresponding to the specified mask. If this leaves * the events mask empty (apart from the POLLHUP bit), set the fd field * to -1 so that poll(2) will ignore this fd. */void__fd_clr(int fd, __evEmulMask *maskp) { evContext_p *ctx = maskp->ctx; *__fd_eventfield(fd, maskp) &= ~__poll_event(maskp); if ((ctx->pollfds[fd].events & ~POLLHUP) == 0) { ctx->pollfds[fd].fd = -1; if (fd == ctx->fdMax) while (ctx->fdMax > ctx->firstfd && ctx->pollfds[ctx->fdMax].fd < 0) ctx->fdMax--; if (fd == ctx->firstfd) while (ctx->firstfd <= ctx->fdMax && ctx->pollfds[ctx->firstfd].fd < 0) ctx->firstfd++; /* * Do we have a empty set of descriptors? */ if (ctx->firstfd > ctx->fdMax) { ctx->fdMax = -1; ctx->firstfd = 0; } }} /* * Set the events bit(s) corresponding to the specified mask. If the events * field has any other bits than POLLHUP set, also set the fd field so that * poll(2) will watch this fd. */void__fd_set(int fd, __evEmulMask *maskp) { evContext_p *ctx = maskp->ctx; *__fd_eventfield(fd, maskp) |= __poll_event(maskp); if ((ctx->pollfds[fd].events & ~POLLHUP) != 0) { ctx->pollfds[fd].fd = fd; if (fd < ctx->firstfd || ctx->fdMax == -1) ctx->firstfd = fd; if (fd > ctx->fdMax) ctx->fdMax = fd; }}#endif /* USE_POLL *//*! \file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -