1 /************************************************************************/
2 /* The ocaml-libevent library */
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 */
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))
27 #define Is_some(v) (Is_block(v))
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
));
41 struct_event_finalize(value ve
)
43 struct event
*ev
= struct_event_val(ve
);
49 struct_event_val(ve
) = NULL
;
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;
64 struct_event_hash(value v
)
66 return (long) struct_event_val(v
);
69 static struct custom_operations struct_event_ops
= {
71 struct_event_finalize
,
74 custom_serialize_default
,
75 custom_deserialize_default
,
76 #if defined(custom_compare_ext_default)
77 custom_compare_ext_default
,
82 struct_event_base_finalize(value vbase
)
84 struct event_base
* base
= struct_event_base_val(vbase
);
87 event_base_free(base
);
88 struct_event_base_val(vbase
) = NULL
;
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;
103 struct_event_base_hash(value v
)
105 return (long) struct_event_base_val(v
);
108 static struct custom_operations struct_event_base_ops
= {
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
,
120 static struct event_base
*
121 get_struct_event_base_val(value v
)
123 struct event_base
* base
= struct_event_base_val(v
);
126 raise_error("event_base","NULL");
132 * This callback calls the ocaml event callback, which will in turn
133 * call the real ocaml callback.
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();
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
));
153 oc_create_event(value u
)
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
;
167 oc_event_id(value vevent
)
170 CAMLreturn(Val_long((long) struct_event_val(vevent
)));
174 oc_event_fd(value vevent
)
177 CAMLreturn(Val_long(EVENT_FD(struct_event_val(vevent
))));
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
),
191 if (0 != event_base_set(base
, event
))
193 raise_error("event_base_set", NULL
);
196 CAMLreturn(Val_unit
);
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));
212 if (0 != event_add(event
, tv
)) {
213 raise_error("event_add", NULL
);
216 CAMLreturn(Val_unit
);
220 oc_event_del(value vevent
)
223 struct event
*event
= struct_event_val(vevent
);
227 CAMLreturn(Val_unit
);
231 oc_event_pending(value vevent
, value vtype
)
233 CAMLparam2(vevent
, vtype
);
234 struct event
*event
= struct_event_val(vevent
);
237 r
= event_pending(event
, Int_val(vtype
), NULL
);
239 CAMLreturn(Val_bool(r
));
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
);
254 oc_event_base_loop(value vbase
, value vflags
)
256 CAMLparam2(vbase
,vflags
);
257 struct event_base
* base
= get_struct_event_base_val(vbase
);
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
);
280 oc_event_base_dispatch(value 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
299 oc_event_base_init(value unit
)
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();
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
;
325 oc_event_base_reinit(value 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
);
338 oc_event_base_free(value 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
);