release 0.9.0
[ocaml-event.git] / event_stubs.c
blob78f92fd4c733c4cdc8b71549e508123456cbdbd2
1 /************************************************************************/
2 /* The ocaml-libevent library */
3 /* */
4 /* Copyright 2002, 2003, 2004 Maas-Maarten Zeeman. All rights reserved. */
5 /* Copyright 2010 ygrek */
6 /* See LICENCE for details. */
7 /************************************************************************/
9 /* Stub code to interface Ocaml with libevent */
11 #include <sys/time.h>
12 #include <stdlib.h>
13 #include <event.h>
14 #include <string.h>
16 #include <caml/mlvalues.h>
17 #include <caml/custom.h>
18 #include <caml/alloc.h>
19 #include <caml/memory.h>
20 #include <caml/callback.h>
21 #include <caml/fail.h>
22 #include <caml/unixsupport.h>
23 #include <caml/signals.h>
25 #define struct_event_val(v) (*(struct event**) Data_custom_val(v))
26 #ifndef Is_some
27 #define Is_some(v) (Is_block(v))
28 #endif
30 #define struct_event_base_val(v) (*(struct event_base**) Data_custom_val(v))
32 static value const * event_cb_closure = NULL;
34 /* FIXME use dedicated exception */
35 static void raise_error(char const* str, char const* arg)
37 uerror((char*)str, NULL == arg ? Nothing : caml_copy_string(arg));
40 static void
41 struct_event_finalize(value ve)
43 struct event *ev = struct_event_val(ve);
45 if (NULL != ev)
47 event_del(ev);
48 caml_stat_free(ev);
49 struct_event_val(ve) = NULL;
53 static int
54 struct_event_compare(value v1, value v2)
56 struct event *p1 = struct_event_val(v1);
57 struct event *p2 = struct_event_val(v2);
58 if(p1 == p2) return 0;
59 if(p1 < p2) return -1;
60 return 1;
63 static long
64 struct_event_hash(value v)
66 return (long) struct_event_val(v);
69 static struct custom_operations struct_event_ops = {
70 "struct event",
71 struct_event_finalize,
72 struct_event_compare,
73 struct_event_hash,
74 custom_serialize_default,
75 custom_deserialize_default,
76 #if defined(custom_compare_ext_default)
77 custom_compare_ext_default,
78 #endif
81 static void
82 struct_event_base_finalize(value vbase)
84 struct event_base* base = struct_event_base_val(vbase);
85 if (NULL != base)
87 event_base_free(base);
88 struct_event_base_val(vbase) = NULL;
92 static int
93 struct_event_base_compare(value v1, value v2)
95 struct event_base *p1 = struct_event_base_val(v1);
96 struct event_base *p2 = struct_event_base_val(v2);
97 if(p1 == p2) return 0;
98 if(p1 < p2) return -1;
99 return 1;
102 static long
103 struct_event_base_hash(value v)
105 return (long) struct_event_base_val(v);
108 static struct custom_operations struct_event_base_ops = {
109 "struct event_base",
110 struct_event_base_finalize,
111 struct_event_base_compare,
112 struct_event_base_hash,
113 custom_serialize_default,
114 custom_deserialize_default,
115 #if defined(custom_compare_ext_default)
116 custom_compare_ext_default,
117 #endif
120 static struct event_base*
121 get_struct_event_base_val(value v)
123 struct event_base* base = struct_event_base_val(v);
124 if (NULL == base)
126 raise_error("event_base","NULL");
128 return base;
132 * This callback calls the ocaml event callback, which will in turn
133 * call the real ocaml callback.
135 static void
136 event_cb(int fd, short type, void *arg)
138 caml_leave_blocking_section();
139 caml_callback3(*event_cb_closure,
140 Val_long((long) arg), Val_int(fd), Val_int(type));
141 caml_enter_blocking_section();
144 static void
145 set_struct_timeval(struct timeval *tv, value vfloat)
147 double timeout = Double_val(vfloat);
148 tv->tv_sec = (int) timeout;
149 tv->tv_usec = (int) (1e6 * (timeout - tv->tv_sec));
152 CAMLprim value
153 oc_create_event(value u)
155 CAMLparam1(u);
156 CAMLlocal1(ve);
157 struct event* ev = caml_stat_alloc(sizeof(struct event));
158 memset(ev, 0, sizeof(*ev));
160 ve = caml_alloc_custom(&struct_event_ops, sizeof(struct event*), 0, 1);
161 struct_event_val(ve) = ev;
163 CAMLreturn(ve);
166 CAMLprim value
167 oc_event_id(value vevent)
169 CAMLparam0();
170 CAMLreturn(Val_long((long) struct_event_val(vevent)));
173 CAMLprim value
174 oc_event_fd(value vevent)
176 CAMLparam1(vevent);
177 CAMLreturn(Val_long(EVENT_FD(struct_event_val(vevent))));
180 CAMLprim value
181 oc_event_set(value vbase, value vevent, value fd, value vevent_flag)
183 CAMLparam4(vbase, vevent, fd, vevent_flag);
185 struct event *event = struct_event_val(vevent);
186 struct event_base* base = get_struct_event_base_val(vbase);
188 event_set(event, Int_val(fd), Int_val(vevent_flag),
189 &event_cb, event);
191 if (0 != event_base_set(base, event))
193 raise_error("event_base_set", NULL);
196 CAMLreturn(Val_unit);
199 CAMLprim value
200 oc_event_add(value vevent, value vfloat_option)
202 CAMLparam2(vevent, vfloat_option);
203 struct event *event = struct_event_val(vevent);
204 struct timeval timeval;
205 struct timeval *tv = NULL;
207 if (Is_some(vfloat_option)) {
208 set_struct_timeval(&timeval, Field(vfloat_option, 0));
209 tv = &timeval;
212 if (0 != event_add(event, tv)) {
213 raise_error("event_add", NULL);
216 CAMLreturn(Val_unit);
219 CAMLprim value
220 oc_event_del(value vevent)
222 CAMLparam0();
223 struct event *event = struct_event_val(vevent);
225 event_del(event);
227 CAMLreturn(Val_unit);
230 CAMLprim value
231 oc_event_pending(value vevent, value vtype)
233 CAMLparam2(vevent, vtype);
234 struct event *event = struct_event_val(vevent);
235 int r = 0;
237 r = event_pending(event, Int_val(vtype), NULL);
239 CAMLreturn(Val_bool(r));
242 CAMLprim value
243 oc_event_active(value vevent, value vtype)
245 CAMLparam2(vevent, vtype);
246 struct event *event = struct_event_val(vevent);
248 event_active(event, Int_val(vtype), 0);
250 CAMLreturn(Val_unit);
253 CAMLprim value
254 oc_event_base_loop(value vbase, value vflags)
256 CAMLparam2(vbase,vflags);
257 struct event_base* base = get_struct_event_base_val(vbase);
258 int flags = 0;
259 while (vflags != Val_emptylist)
261 if (0 == Int_val(Field(vflags,0))) flags |= EVLOOP_ONCE;
262 else if (1 == Int_val(Field(vflags,0))) flags |= EVLOOP_NONBLOCK;
263 else caml_invalid_argument("Libevent.loops");
265 vflags = Field(vflags,1);
268 caml_enter_blocking_section();
269 if((-1 == event_base_loop(base,flags))) {
270 caml_leave_blocking_section();
271 raise_error("event_base_loop", NULL);
273 caml_leave_blocking_section();
275 CAMLreturn(Val_unit);
279 CAMLprim value
280 oc_event_base_dispatch(value vbase)
282 CAMLparam1(vbase);
283 struct event_base* base = get_struct_event_base_val(vbase);
285 caml_enter_blocking_section();
286 if((-1 == event_base_dispatch(base))) {
287 caml_leave_blocking_section();
288 raise_error("event_base_dispatch", NULL);
290 caml_leave_blocking_section();
292 CAMLreturn(Val_unit);
296 * Initialize event base
298 CAMLprim value
299 oc_event_base_init(value unit)
301 CAMLparam1(unit);
302 CAMLlocal1(v);
303 struct event_base* base = NULL;
305 /* setup the event callback closure if needed */
306 if(event_cb_closure == NULL) {
307 event_cb_closure = caml_named_value("event_cb");
308 if(event_cb_closure == NULL) {
309 caml_invalid_argument("Callback event_cb not initialized.");
313 base = event_base_new();
314 if (!base) {
315 raise_error("event_base_init", NULL);
318 v = caml_alloc_custom(&struct_event_base_ops, sizeof(struct event_base*), 0, 1);
319 struct_event_base_val(v) = base;
321 CAMLreturn(v);
324 CAMLprim value
325 oc_event_base_reinit(value vbase)
327 CAMLparam1(vbase);
328 struct event_base* base = get_struct_event_base_val(vbase);
330 if (0 != event_reinit(base)) {
331 raise_error("event_base_reinit", NULL);
334 CAMLreturn(Val_unit);
337 CAMLprim value
338 oc_event_base_free(value vbase)
340 CAMLparam1(vbase);
342 struct event_base* base = get_struct_event_base_val(vbase);
343 event_base_free(base);
344 struct_event_base_val(vbase) = NULL;
346 CAMLreturn(Val_unit);