5 #include "fdevent_impl.h"
9 #ifdef FDEVENT_USE_LIBEV
13 static void io_watcher_cb(struct ev_loop
*loop
, ev_io
*w
, int revents
) {
14 fdevents
*ev
= w
->data
;
15 fdnode
*fdn
= ev
->fdarray
[w
->fd
];
19 if (revents
& EV_READ
) r
|= FDEVENT_IN
;
20 if (revents
& EV_WRITE
) r
|= FDEVENT_OUT
;
21 if (revents
& EV_ERROR
) r
|= FDEVENT_ERR
;
23 if (0 == ((uintptr_t)fdn
& 0x3)) {
24 (*fdn
->handler
)(ev
->srv
, fdn
->ctx
, r
);
29 static void fdevent_libev_free(fdevents
*ev
) {
33 static int fdevent_libev_event_del(fdevents
*ev
, fdnode
*fdn
) {
34 ev_io
*watcher
= fdn
->handler_ctx
;
35 if (!watcher
) return 0;
36 fdn
->handler_ctx
= NULL
;
38 ev_io_stop(ev
->libev_loop
, watcher
);
44 static int fdevent_libev_event_set(fdevents
*ev
, fdnode
*fdn
, int events
) {
45 ev_io
*watcher
= fdn
->handler_ctx
;
48 if (events
& FDEVENT_IN
) ev_events
|= EV_READ
;
49 if (events
& FDEVENT_OUT
) ev_events
|= EV_WRITE
;
52 fdn
->handler_ctx
= watcher
= calloc(1, sizeof(ev_io
));
53 force_assert(watcher
);
54 fdn
->fde_ndx
= fdn
->fd
;
56 ev_io_init(watcher
, io_watcher_cb
, fdn
->fd
, ev_events
);
58 ev_io_start(ev
->libev_loop
, watcher
);
60 if ((watcher
->events
& (EV_READ
| EV_WRITE
)) != ev_events
) {
61 ev_io_stop(ev
->libev_loop
, watcher
);
62 ev_io_set(watcher
, watcher
->fd
, ev_events
);
63 ev_io_start(ev
->libev_loop
, watcher
);
70 static void timeout_watcher_cb(struct ev_loop
*loop
, ev_timer
*w
, int revents
) {
76 static ev_timer timeout_watcher
;
78 static int fdevent_libev_poll(fdevents
*ev
, int timeout_ms
) {
79 timeout_watcher
.repeat
= (timeout_ms
> 0) ? timeout_ms
/1000.0 : 0.001;
81 ev_timer_again(ev
->libev_loop
, &timeout_watcher
);
82 ev_run(ev
->libev_loop
, EVRUN_ONCE
);
88 static int fdevent_libev_reset(fdevents
*ev
) {
95 int fdevent_libev_init(fdevents
*ev
) {
96 struct ev_timer
* const timer
= &timeout_watcher
;
97 memset(timer
, 0, sizeof(*timer
));
99 ev
->type
= FDEVENT_HANDLER_LIBEV
;
100 ev
->event_set
= fdevent_libev_event_set
;
101 ev
->event_del
= fdevent_libev_event_del
;
102 ev
->poll
= fdevent_libev_poll
;
103 ev
->reset
= fdevent_libev_reset
;
104 ev
->free
= fdevent_libev_free
;
106 if (NULL
== (ev
->libev_loop
= ev_default_loop(0))) return -1;
108 ev_timer_init(timer
, timeout_watcher_cb
, 0.0, 1.0);