9c7c32449c7244a37eb015c4cef2d698a258f743
[platform/upstream/krb5.git] / src / util / verto / verto-libev.c
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 (verto_get_type(w->data)== VERTO_EV_TYPE_CHILD)
84         verto_set_proc_status(w->data, ((ev_child*) w)->rstatus);
85
86     if (revents & EV_READ)
87         state |= VERTO_EV_FLAG_IO_READ;
88     if (revents & EV_WRITE)
89         state |= VERTO_EV_FLAG_IO_WRITE;
90     if (revents & EV_ERROR)
91         state |= VERTO_EV_FLAG_IO_ERROR;
92
93     verto_set_fd_state(w->data, state);
94     verto_fire(w->data);
95 }
96
97 static void
98 libev_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev,
99                     verto_mod_ev *evpriv)
100 {
101     if (verto_get_type(ev) == VERTO_EV_TYPE_IO) {
102         int events = EV_NONE;
103
104         if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ)
105             events |= EV_READ;
106         if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE)
107             events |= EV_WRITE;
108
109         ev_io_stop(ctx, (ev_io*) evpriv);
110         ev_io_set(((ev_io*) evpriv), verto_get_fd(ev), events);
111         ev_io_start(ctx, (ev_io*) evpriv);
112     }
113 }
114
115 #define setuptype(type, ...) \
116     w.type = malloc(sizeof(ev_ ## type)); \
117     if (w.type) { \
118         ev_ ## type ## _init(w.type, (EV_CB(type, (*))) __VA_ARGS__); \
119         ev_ ## type ## _start(ctx, w.type); \
120     } \
121     break
122
123 static verto_mod_ev *
124 libev_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags)
125 {
126     union {
127        ev_watcher *watcher;
128        ev_io *io;
129        ev_timer *timer;
130        ev_idle *idle;
131        ev_signal *signal;
132        ev_child *child;
133     } w;
134     ev_tstamp interval;
135
136     w.watcher = NULL;
137     *flags |= VERTO_EV_FLAG_PERSIST;
138     switch (verto_get_type(ev)) {
139         case VERTO_EV_TYPE_IO:
140             setuptype(io, libev_callback, verto_get_fd(ev), EV_NONE);
141         case VERTO_EV_TYPE_TIMEOUT:
142             interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0;
143             setuptype(timer, libev_callback, interval, interval);
144         case VERTO_EV_TYPE_IDLE:
145             setuptype(idle, libev_callback);
146         case VERTO_EV_TYPE_SIGNAL:
147             setuptype(signal, libev_callback, verto_get_signal(ev));
148         case VERTO_EV_TYPE_CHILD:
149             *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */
150             setuptype(child, libev_callback, verto_get_proc(ev), 0);
151         default:
152             break; /* Not supported */
153     }
154
155     if (w.watcher) {
156         w.watcher->data = (void*) ev;
157         libev_ctx_set_flags(ctx, ev, w.watcher);
158     }
159     return w.watcher;
160 }
161
162 static void
163 libev_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv)
164 {
165     switch (verto_get_type(ev)) {
166         case VERTO_EV_TYPE_IO:
167             ev_io_stop(ctx, (ev_io*) evpriv);
168             break;
169         case VERTO_EV_TYPE_TIMEOUT:
170             ev_timer_stop(ctx, (ev_timer*) evpriv);
171             break;
172         case VERTO_EV_TYPE_IDLE:
173             ev_idle_stop(ctx, (ev_idle*) evpriv);
174             break;
175         case VERTO_EV_TYPE_SIGNAL:
176             ev_signal_stop(ctx, (ev_signal*) evpriv);
177             break;
178         case VERTO_EV_TYPE_CHILD:
179             ev_child_stop(ctx, (ev_child*) evpriv);
180             break;
181         default:
182             break;
183     }
184
185     free(evpriv);
186 }
187
188 VERTO_MODULE(libev, ev_loop_new,
189              VERTO_EV_TYPE_IO |
190              VERTO_EV_TYPE_TIMEOUT |
191              VERTO_EV_TYPE_IDLE |
192              VERTO_EV_TYPE_SIGNAL |
193              VERTO_EV_TYPE_CHILD);
194
195 verto_ctx *
196 verto_convert_libev(struct ev_loop* loop)
197 {
198     return verto_convert(libev, 0, loop);
199 }