1 /* 2 * Copyright 2011 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation files 6 * (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include <stdlib.h> 26 #include <string.h> 27 #include <errno.h> 28 29 #include <verto-libev.h> 30 #define VERTO_MODULE_TYPES 31 typedef struct ev_loop verto_mod_ctx; 32 typedef ev_watcher verto_mod_ev; 33 #include <verto-module.h> 34 35 static verto_mod_ctx * 36 libev_ctx_new(void) 37 { 38 return ev_loop_new(EVFLAG_AUTO); 39 } 40 41 static verto_mod_ctx * 42 libev_ctx_default(void) 43 { 44 return ev_default_loop(EVFLAG_AUTO); 45 } 46 47 static void 48 libev_ctx_free(verto_mod_ctx *ctx) 49 { 50 if (ctx != EV_DEFAULT) 51 ev_loop_destroy(ctx); 52 } 53 54 static void 55 libev_ctx_run(verto_mod_ctx *ctx) 56 { 57 ev_run(ctx, 0); 58 } 59 60 static void 61 libev_ctx_run_once(verto_mod_ctx *ctx) 62 { 63 ev_run(ctx, EVRUN_ONCE); 64 } 65 66 static void 67 libev_ctx_break(verto_mod_ctx *ctx) 68 { 69 ev_break(ctx, EVBREAK_ONE); 70 } 71 72 static void 73 libev_ctx_reinitialize(verto_mod_ctx *ctx) 74 { 75 ev_loop_fork(ctx); 76 } 77 78 static void 79 libev_callback(EV_P_ ev_watcher *w, int revents) 80 { 81 verto_ev_flag state = VERTO_EV_FLAG_NONE; 82 83 #if EV_MULTIPLICITY 84 /* Match the check in ev.h, which doesn't mark this unused */ 85 (void) EV_A; 86 #endif 87 88 if (verto_get_type(w->data)== VERTO_EV_TYPE_CHILD) 89 verto_set_proc_status(w->data, ((ev_child*) w)->rstatus); 90 91 if (revents & EV_READ) 92 state |= VERTO_EV_FLAG_IO_READ; 93 if (revents & EV_WRITE) 94 state |= VERTO_EV_FLAG_IO_WRITE; 95 if (revents & EV_ERROR) 96 state |= VERTO_EV_FLAG_IO_ERROR; 97 98 verto_set_fd_state(w->data, state); 99 verto_fire(w->data); 100 } 101 102 static void 103 libev_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev, 104 verto_mod_ev *evpriv) 105 { 106 if (verto_get_type(ev) == VERTO_EV_TYPE_IO) { 107 int events = EV_NONE; 108 109 if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ) 110 events |= EV_READ; 111 if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE) 112 events |= EV_WRITE; 113 114 ev_io_stop(ctx, (ev_io*) evpriv); 115 ev_io_set(((ev_io*) evpriv), verto_get_fd(ev), events); 116 ev_io_start(ctx, (ev_io*) evpriv); 117 } 118 } 119 120 #define setuptype(type, ...) \ 121 w.type = malloc(sizeof(ev_ ## type)); \ 122 if (w.type) { \ 123 ev_ ## type ## _init(w.type, (EV_CB(type, (*))) __VA_ARGS__); \ 124 ev_ ## type ## _start(ctx, w.type); \ 125 } \ 126 break 127 128 static verto_mod_ev * 129 libev_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) 130 { 131 union { 132 ev_watcher *watcher; 133 ev_io *io; 134 ev_timer *timer; 135 ev_idle *idle; 136 ev_signal *signal; 137 ev_child *child; 138 } w; 139 ev_tstamp interval; 140 141 w.watcher = NULL; 142 *flags |= VERTO_EV_FLAG_PERSIST; 143 switch (verto_get_type(ev)) { 144 case VERTO_EV_TYPE_IO: 145 setuptype(io, libev_callback, verto_get_fd(ev), EV_NONE); 146 case VERTO_EV_TYPE_TIMEOUT: 147 interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0; 148 setuptype(timer, libev_callback, interval, interval); 149 case VERTO_EV_TYPE_IDLE: 150 setuptype(idle, libev_callback); 151 case VERTO_EV_TYPE_SIGNAL: 152 setuptype(signal, libev_callback, verto_get_signal(ev)); 153 case VERTO_EV_TYPE_CHILD: 154 *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */ 155 setuptype(child, libev_callback, verto_get_proc(ev), 0); 156 default: 157 break; /* Not supported */ 158 } 159 160 if (w.watcher) { 161 w.watcher->data = (void*) ev; 162 libev_ctx_set_flags(ctx, ev, w.watcher); 163 } 164 return w.watcher; 165 } 166 167 static void 168 libev_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) 169 { 170 switch (verto_get_type(ev)) { 171 case VERTO_EV_TYPE_IO: 172 ev_io_stop(ctx, (ev_io*) evpriv); 173 break; 174 case VERTO_EV_TYPE_TIMEOUT: 175 ev_timer_stop(ctx, (ev_timer*) evpriv); 176 break; 177 case VERTO_EV_TYPE_IDLE: 178 ev_idle_stop(ctx, (ev_idle*) evpriv); 179 break; 180 case VERTO_EV_TYPE_SIGNAL: 181 ev_signal_stop(ctx, (ev_signal*) evpriv); 182 break; 183 case VERTO_EV_TYPE_CHILD: 184 ev_child_stop(ctx, (ev_child*) evpriv); 185 break; 186 default: 187 break; 188 } 189 190 free(evpriv); 191 } 192 193 VERTO_MODULE(libev, ev_loop_new, 194 VERTO_EV_TYPE_IO | 195 VERTO_EV_TYPE_TIMEOUT | 196 VERTO_EV_TYPE_IDLE | 197 VERTO_EV_TYPE_SIGNAL | 198 VERTO_EV_TYPE_CHILD); 199 200 verto_ctx * 201 verto_convert_libev(struct ev_loop* loop) 202 { 203 return verto_convert(libev, 0, loop); 204 } 205