#ifndef __HEV_TASK_IO_REACTOR_KQUEUE_H__
#define __HEV_TASK_IO_REACTOR_KQUEUE_H__
#include <poll.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#ifndef EVFILT_EXCEPT
#define EVFILT_EXCEPT (0)
#endif
#define HEV_TASK_IO_REACTOR_EVENT_GEN_MAX (6)
typedef struct _HevTaskIOReactorKQueue HevTaskIOReactorKQueue;
typedef struct kevent HevTaskIOReactorSetupEvent;
typedef struct kevent HevTaskIOReactorWaitEvent;
struct _HevTaskIOReactorKQueue
{
HevTaskIOReactor base;
};
enum _HevTaskIOReactorEvents
{
HEV_TASK_IO_REACTOR_EV_RO = EVFILT_READ,
HEV_TASK_IO_REACTOR_EV_WO = EVFILT_WRITE,
HEV_TASK_IO_REACTOR_EV_ER = EVFILT_EXCEPT,
};
enum _HevTaskIOReactorOperation
{
HEV_TASK_IO_REACTOR_OP_ADD,
HEV_TASK_IO_REACTOR_OP_MOD,
HEV_TASK_IO_REACTOR_OP_DEL,
};
static inline int
hev_task_io_reactor_open (void)
{
return kqueue ();
}
static inline int
hev_task_io_reactor_wait (HevTaskIOReactor *reactor,
HevTaskIOReactorWaitEvent *events, int count,
int timeout)
{
struct timespec tsz = { 0 };
struct timespec *tsp = NULL;
if (timeout >= 0)
tsp = &tsz;
return kevent (reactor->fd, NULL, 0, events, count, tsp);
}
static inline void
hev_task_io_reactor_setup_event_set (HevTaskIOReactorSetupEvent *event, int fd,
HevTaskIOReactorOperation op,
unsigned int events, void *data)
{
int action;
switch (op) {
case HEV_TASK_IO_REACTOR_OP_ADD:
case HEV_TASK_IO_REACTOR_OP_MOD:
action = EV_ADD;
break;
case HEV_TASK_IO_REACTOR_OP_DEL:
action = EV_DELETE;
}
EV_SET (event, fd, events, action | EV_CLEAR, 0, 0, data);
}
static inline int
hev_task_io_reactor_setup_event_gen (HevTaskIOReactorSetupEvent *events, int fd,
HevTaskIOReactorOperation op,
unsigned int poll_events, void *data)
{
int count = 0;
if (op > HEV_TASK_IO_REACTOR_OP_ADD) {
if (!(poll_events & POLLIN))
hev_task_io_reactor_setup_event_set (&events[count++], fd,
HEV_TASK_IO_REACTOR_OP_DEL,
HEV_TASK_IO_REACTOR_EV_RO,
data);
if (!(poll_events & POLLOUT))
hev_task_io_reactor_setup_event_set (&events[count++], fd,
HEV_TASK_IO_REACTOR_OP_DEL,
HEV_TASK_IO_REACTOR_EV_WO,
data);
if (!(poll_events & POLLERR))
hev_task_io_reactor_setup_event_set (&events[count++], fd,
HEV_TASK_IO_REACTOR_OP_DEL,
HEV_TASK_IO_REACTOR_EV_ER,
data);
if (op == HEV_TASK_IO_REACTOR_OP_DEL)
return count;
}
if (poll_events & POLLIN)
hev_task_io_reactor_setup_event_set (&events[count++], fd, op,
HEV_TASK_IO_REACTOR_EV_RO, data);
if (poll_events & POLLOUT)
hev_task_io_reactor_setup_event_set (&events[count++], fd, op,
HEV_TASK_IO_REACTOR_EV_WO, data);
if (poll_events & POLLERR)
hev_task_io_reactor_setup_event_set (&events[count++], fd, op,
HEV_TASK_IO_REACTOR_EV_ER, data);
return count;
}
static inline unsigned int
hev_task_io_reactor_wait_event_get_events (HevTaskIOReactorWaitEvent *event)
{
return event->filter;
}
static inline void *
hev_task_io_reactor_wait_event_get_data (HevTaskIOReactorWaitEvent *event)
{
return event->udata;
}
#endif