#include #include #include #include #include "evloop.h" static int m_epfd; static struct epoll_event m_evs[100]; static uint8_t m_valid[100]; int evloop_init(void) { if (timeheap_init() != 0) return -1; m_epfd = epoll_create(getdtablesize()); return m_epfd >= 0 ? 0 : -1; } int fdev_new(struct fdev *ev, int fd, uint16_t flags, evloop_cb_t cb, void *arg) { ev->fd = fd; ev->cb = cb; ev->arg = arg; ev->flags = 0; ev->index = -1; return fdev_enable(ev, flags); } int fdev_enable(struct fdev *ev, uint16_t flags) { struct epoll_event epev; int err = 0; uint16_t sf = ev->flags; ev->flags |= flags; if (sf != ev->flags) { epev.data.ptr = ev; epev.events = ((ev->flags & EV_READ) ? EPOLLIN : 0) | ((ev->flags & EV_WRITE) ? EPOLLOUT : 0); if (sf == 0) err = epoll_ctl(m_epfd, EPOLL_CTL_ADD, ev->fd, &epev); else err = epoll_ctl(m_epfd, EPOLL_CTL_MOD, ev->fd, &epev); } return err; } int fdev_disable(struct fdev *ev, uint16_t flags) { struct epoll_event epev; int err = 0; uint16_t sf = ev->flags; ev->flags &= ~flags; if (sf != ev->flags) { epev.data.ptr = ev; epev.events = ((ev->flags & EV_READ) ? EPOLLIN : 0) | ((ev->flags & EV_WRITE) ? EPOLLOUT : 0); if (ev->flags == 0) err = epoll_ctl(m_epfd, EPOLL_CTL_DEL, ev->fd, &epev); else err = epoll_ctl(m_epfd, EPOLL_CTL_MOD, ev->fd, &epev); } return err; } int fdev_del(struct fdev *ev) { if (ev->index >= 0) m_valid[ev->index] = 0; return fdev_disable(ev, EV_READ|EV_WRITE); } int evloop(void) { int nev, i, millisecs; struct timespec delay; while (1) { evtimers_run(); delay = evtimer_delay(); if (delay.tv_sec >= 0) millisecs = delay.tv_sec * 1000 + delay.tv_nsec / 1000000; else millisecs = -1; if ((nev = epoll_wait(m_epfd, m_evs, 100, millisecs)) < 0) { if (errno == EINTR) continue; else return -1; } memset(m_valid, 1, nev); for (i = 0; i < nev; i++) { struct fdev *ev = m_evs[i].data.ptr; ev->index = i; } for (i = 0; i < nev; i++) { struct fdev *ev = m_evs[i].data.ptr; if ((m_valid[i] && ev->flags & EV_READ && m_evs[i].events & (EPOLLIN|EPOLLERR|EPOLLHUP))) ev->cb(ev->fd, EV_READ, ev->arg); if ((m_valid[i] && ev->flags & EV_WRITE && m_evs[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP))) ev->cb(ev->fd, EV_WRITE, ev->arg); if (m_valid[i]) ev->index = -1; } } }