/* * Copyright (c) 2020 YuQing <384681@qq.com> * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the Lesser GNU General Public License, version 3 * or later ("LGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the Lesser GNU General Public License * along with this program. If not, see . */ #ifndef __IOEVENT_H__ #define __IOEVENT_H__ #include #include #include #include "_os_define.h" #define IOEVENT_TIMEOUT 0x8000 #if IOEVENT_USE_EPOLL #include #define IOEVENT_EDGE_TRIGGER EPOLLET #define IOEVENT_READ EPOLLIN #define IOEVENT_WRITE EPOLLOUT #define IOEVENT_ERROR (EPOLLERR | EPOLLPRI | EPOLLHUP) #elif IOEVENT_USE_KQUEUE #include #include #define IOEVENT_EDGE_TRIGGER EV_CLEAR #define KPOLLIN POLLIN #define KPOLLPRI POLLPRI #define KPOLLOUT POLLOUT #define KPOLLERR POLLERR #define KPOLLHUP POLLHUP #define IOEVENT_READ KPOLLIN #define IOEVENT_WRITE KPOLLOUT #define IOEVENT_ERROR (KPOLLERR | KPOLLHUP | POLLNVAL) #ifdef __cplusplus extern "C" { #endif int kqueue_ev_convert(int16_t event, uint16_t flags); #ifdef __cplusplus } #endif #elif IOEVENT_USE_PORT #include #define IOEVENT_EDGE_TRIGGER 0 #define IOEVENT_READ POLLIN #define IOEVENT_WRITE POLLOUT #define IOEVENT_ERROR (POLLERR | POLLPRI | POLLHUP) #endif typedef struct ioevent_puller { int size; //max events (fd) int extra_events; int poll_fd; struct { int index; int count; } iterator; //for deal event loop #if IOEVENT_USE_EPOLL struct epoll_event *events; int timeout; #elif IOEVENT_USE_KQUEUE struct kevent *events; struct timespec timeout; #elif IOEVENT_USE_PORT port_event_t *events; timespec_t timeout; #endif } IOEventPoller; #if IOEVENT_USE_EPOLL #define IOEVENT_GET_EVENTS(ioevent, index) \ (ioevent)->events[index].events #elif IOEVENT_USE_KQUEUE #define IOEVENT_GET_EVENTS(ioevent, index) kqueue_ev_convert( \ (ioevent)->events[index].filter, (ioevent)->events[index].flags) #elif IOEVENT_USE_PORT #define IOEVENT_GET_EVENTS(ioevent, index) \ (ioevent)->events[index].portev_events #else #error port me #endif #if IOEVENT_USE_EPOLL #define IOEVENT_GET_DATA(ioevent, index) \ (ioevent)->events[index].data.ptr #elif IOEVENT_USE_KQUEUE #define IOEVENT_GET_DATA(ioevent, index) \ (ioevent)->events[index].udata #elif IOEVENT_USE_PORT #define IOEVENT_GET_DATA(ioevent, index) \ (ioevent)->events[index].portev_user #else #error port me #endif #if IOEVENT_USE_EPOLL #define IOEVENT_CLEAR_DATA(ioevent, index) \ (ioevent)->events[index].data.ptr = NULL #elif IOEVENT_USE_KQUEUE #define IOEVENT_CLEAR_DATA(ioevent, index) \ (ioevent)->events[index].udata = NULL #elif IOEVENT_USE_PORT #define IOEVENT_CLEAR_DATA(ioevent, index) \ (ioevent)->events[index].portev_user = NULL #else #error port me #endif #ifdef __cplusplus extern "C" { #endif int ioevent_init(IOEventPoller *ioevent, const int size, const int timeout_ms, const int extra_events); void ioevent_destroy(IOEventPoller *ioevent); int ioevent_attach(IOEventPoller *ioevent, const int fd, const int e, void *data); int ioevent_modify(IOEventPoller *ioevent, const int fd, const int e, void *data); int ioevent_detach(IOEventPoller *ioevent, const int fd); int ioevent_poll(IOEventPoller *ioevent); static inline void ioevent_set_timeout(IOEventPoller *ioevent, const int timeout_ms) { #if IOEVENT_USE_EPOLL ioevent->timeout = timeout_ms; #else ioevent->timeout.tv_sec = timeout_ms / 1000; ioevent->timeout.tv_nsec = 1000000 * (timeout_ms % 1000); #endif } static inline int ioevent_poll_ex(IOEventPoller *ioevent, const int timeout_ms) { ioevent_set_timeout(ioevent, timeout_ms); return ioevent_poll(ioevent); } #ifdef __cplusplus } #endif #endif