21int pselect(
int n, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
22 const struct timespec* timeout,
const sigset_t* sigmask);
24#include <sys/select.h>
28#define NANOSECONDS_PER_SECOND 1000000000L
30static const char* netio_str =
"netio";
57 ods_log_assert(netio);
58 ods_log_assert(handler);
64 ods_log_debug(
"[%s] handler added", netio_str);
75 if (!netio || !handler) {
78 for (lptr = &netio->
handlers; *lptr; lptr = &(*lptr)->
next) {
79 if ((*lptr)->handler == handler) {
90 ods_log_debug(
"[%s] handler removed", netio_str);
99timeval_to_timespec(
struct timespec* left,
const struct timeval* right)
101 left->tv_sec = right->tv_sec;
102 left->tv_nsec = 1000 * right->tv_usec;
110timespec_compare(
const struct timespec* left,
111 const struct timespec* right)
113 if (left->tv_sec < right->tv_sec) {
115 }
else if (left->tv_sec > right->tv_sec) {
117 }
else if (left->tv_nsec < right->tv_nsec) {
119 }
else if (left->tv_nsec > right->tv_nsec) {
133 left->tv_sec += right->tv_sec;
134 left->tv_nsec += right->tv_nsec;
147timespec_subtract(
struct timespec* left,
const struct timespec* right)
149 left->tv_sec -= right->tv_sec;
150 left->tv_nsec -= right->tv_nsec;
151 if (left->tv_nsec < 0L) {
162const struct timespec*
165 struct timeval current_timeval;
166 ods_log_assert(netio);
168 if (gettimeofday(¤t_timeval, NULL) == -1) {
169 ods_log_crit(
"[%s] unable to get current time: "
170 "gettimeofday() failed (%s)", netio_str,
188 const sigset_t* sigmask)
190 fd_set readfds, writefds, exceptfds;
192 int have_timeout = 0;
193 struct timespec minimum_timeout;
207 memcpy(&minimum_timeout, timeout,
sizeof(
struct timespec));
217 if (handler->
fd >= 0 && handler->
fd < (
int) FD_SETSIZE) {
218 if (handler->
fd > max_fd) {
219 max_fd = handler->
fd;
222 FD_SET(handler->
fd, &readfds);
225 FD_SET(handler->
fd, &writefds);
228 FD_SET(handler->
fd, &exceptfds);
233 struct timespec relative;
234 relative.tv_sec = handler->
timeout->tv_sec;
235 relative.tv_nsec = handler->
timeout->tv_nsec;
239 timespec_compare(&relative, &minimum_timeout) < 0) {
241 minimum_timeout.tv_sec = relative.tv_sec;
242 minimum_timeout.tv_nsec = relative.tv_nsec;
243 timeout_handler = handler;
248 if (have_timeout && minimum_timeout.tv_sec < 0) {
253 ods_log_debug(
"[%s] dispatch timeout event without checking for "
254 "other events", netio_str);
255 if (timeout_handler &&
257 timeout_handler->event_handler(netio, timeout_handler,
263 rc =
pselect(max_fd + 1, &readfds, &writefds, &exceptfds,
264 have_timeout ? &minimum_timeout : NULL, sigmask);
266 if(errno == EINVAL || errno == EACCES || errno == EBADF) {
267 ods_fatal_exit(
"[%s] fatal error pselect: %s", netio_str,
278 ods_log_debug(
"[%s] no events before the minimum timeout "
279 "expired", netio_str);
284 if (timeout_handler &&
286 timeout_handler->event_handler(netio, timeout_handler,
297 for (l = netio->
handlers; l && rc; ) {
300 if (handler->
fd >= 0 && handler->
fd < (
int) FD_SETSIZE) {
302 if (FD_ISSET(handler->
fd, &readfds)) {
304 FD_CLR(handler->
fd, &readfds);
307 if (FD_ISSET(handler->
fd, &writefds)) {
309 FD_CLR(handler->
fd, &writefds);
312 if (FD_ISSET(handler->
fd, &exceptfds)) {
314 FD_CLR(handler->
fd, &exceptfds);
338 ods_log_assert(netio);
357 ods_log_assert(netio);
const struct timespec * netio_current_time(netio_type *netio)
void netio_cleanup_shallow(netio_type *netio)
#define NANOSECONDS_PER_SECOND
void netio_remove_handler(netio_type *netio, netio_handler_type *handler)
int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask)
void timespec_add(struct timespec *left, const struct timespec *right)
void netio_cleanup(netio_type *netio)
int netio_dispatch(netio_type *netio, const struct timespec *timeout, const sigset_t *sigmask)
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
netio_type * netio_create()
enum netio_events_enum netio_events_type
netio_handler_list_type * next
netio_handler_type * handler
struct timespec * timeout
netio_events_type event_types
netio_event_handler_type event_handler
netio_handler_list_type * dispatch_next
netio_handler_list_type * handlers
struct timespec cached_current_time