int picoev_update_events_internal(picoev_loop* _loop, int fd, int events) { picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop; picoev_fd* target = picoev.fds + fd; assert(PICOEV_FD_BELONGS_TO_LOOP(&loop->loop, fd)); /* initialize if adding the fd */ if ((events & PICOEV_ADD) != 0) { target->_backend = -1; } /* return if nothing to do */ if (events == PICOEV_DEL ? target->_backend == -1 : (events & PICOEV_READWRITE) == target->events) { return 0; } /* add to changed list if not yet being done */ if (target->_backend == -1) { target->_backend = BACKEND_BUILD(loop->changed_fds, target->events); loop->changed_fds = fd; } /* update events */ target->events = events & PICOEV_READWRITE; /* apply immediately if is a DELETE */ if ((events & PICOEV_DEL) != 0) { apply_pending_changes(loop, 1); } return 0; }
int picoev_poll_once_internal(picoev_loop* _loop, int max_wait) { picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop; struct timespec ts; int cl_off = 0, nevents, i; /* apply pending changes, with last changes stored to loop->changelist */ cl_off = apply_pending_changes(loop, 0); ts.tv_sec = max_wait; ts.tv_nsec = 0; nevents = kevent(loop->kq, loop->changelist, cl_off, loop->events, sizeof(loop->events) / sizeof(loop->events[0]), &ts); if (nevents == -1) { /* the errors we can only rescue */ assert(errno == EACCES || errno == EFAULT || errno == EINTR); return -1; } for (i = 0; i < nevents; ++i) { struct kevent* event = loop->events + i; picoev_fd* target = picoev.fds + event->ident; assert((event->flags & EV_ERROR) == 0); /* changelist errors are fatal */ if (loop->loop.loop_id == target->loop_id && (event->flags & (EVFILT_READ | EVFILT_WRITE)) != 0) { int revents = ((event->flags & EVFILT_READ) != 0 ? PICOEV_READ : 0) | ((event->flags & EVFILT_WRITE) != 0 ? PICOEV_WRITE : 0); (*target->callback)(&loop->loop, event->ident, revents, target->cb_arg); } } return 0; }
int picoev_poll_once_internal(picoev_loop* _loop, int max_wait) { picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop; struct timespec ts; int cl_off = 0, nevents, i; /* apply pending changes, with last changes stored to loop->changelist */ cl_off = apply_pending_changes(loop, 0); ts.tv_sec = max_wait; ts.tv_nsec = 0; Py_BEGIN_ALLOW_THREADS nevents = kevent(loop->kq, loop->changelist, cl_off, loop->events, sizeof(loop->events) / sizeof(loop->events[0]), &ts); Py_END_ALLOW_THREADS cache_time_update(); if (nevents == -1) { /* the errors we can only rescue */ assert(errno == EACCES || errno == EFAULT || errno == EINTR); return -1; } for (i = 0; i < nevents; ++i) { struct kevent* event = loop->events + i; picoev_fd* target = picoev.fds + event->ident; assert((event->flags & EV_ERROR) == 0); /* changelist errors are fatal */ if (loop->loop.loop_id == target->loop_id && (event->filter & (EVFILT_READ | EVFILT_WRITE)) != 0) { int revents; switch (event->filter) { case EVFILT_READ: revents = PICOEV_READ; break; case EVFILT_WRITE: revents = PICOEV_WRITE; break; default: assert(0); revents = 0; // suppress compiler warning break; } (*target->callback)(&loop->loop, event->ident, revents, target->cb_arg); } } return 0; }