1 /************************************************************************/
2 /* The ocaml-event 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))
26 #define Is_some(v) (Is_block(v))
28 #define struct_event_base_val(v) (*(struct event_base**) Data_custom_val(v))
30 static value
* event_cb_closure
= NULL
;
32 /* FIXME use dedicated exception */
33 static void raise_error(char const* str
, char const* arg
)
35 uerror((char*)str
, NULL
== arg
? Nothing
: caml_copy_string(arg
));
39 struct_event_finalize(value ve
)
41 struct event
*ev
= struct_event_val(ve
);
43 if (event_pending(ev
,EV_TIMEOUT
|EV_READ
|EV_WRITE
|EV_SIGNAL
,NULL
)) {
47 caml_stat_free(struct_event_val(ve
));
51 struct_event_compare(value v1
, value v2
)
53 struct event
*p1
= struct_event_val(v1
);
54 struct event
*p2
= struct_event_val(v2
);
55 if(p1
== p2
) return 0;
56 if(p1
< p2
) return -1;
61 struct_event_hash(value v
)
63 return (long) struct_event_val(v
);
66 static struct custom_operations struct_event_ops
= {
68 struct_event_finalize
,
71 custom_serialize_default
,
72 custom_deserialize_default
,
73 #if defined(custom_compare_ext_default)
74 custom_compare_ext_default
,
79 struct_event_base_finalize(value vbase
)
81 struct event_base
* base
= struct_event_base_val(vbase
);
84 event_base_free(base
);
85 struct_event_base_val(vbase
) = NULL
;
90 struct_event_base_compare(value v1
, value v2
)
92 struct event_base
*p1
= struct_event_base_val(v1
);
93 struct event_base
*p2
= struct_event_base_val(v2
);
94 if(p1
== p2
) return 0;
95 if(p1
< p2
) return -1;
100 struct_event_base_hash(value v
)
102 return (long) struct_event_base_val(v
);
105 static struct custom_operations struct_event_base_ops
= {
107 struct_event_base_finalize
,
108 struct_event_base_compare
,
109 struct_event_base_hash
,
110 custom_serialize_default
,
111 custom_deserialize_default
,
112 #if defined(custom_compare_ext_default)
113 custom_compare_ext_default
,
117 static struct event_base
*
118 get_struct_event_base_val(value v
)
120 struct event_base
* base
= struct_event_base_val(v
);
123 raise_error("event_base","NULL");
129 * This callback calls the ocaml event callback, which will in turn
130 * call the real ocaml callback.
133 event_cb(int fd
, short type
, void *arg
)
135 caml_leave_blocking_section();
136 callback3(*event_cb_closure
,
137 Val_long((long) arg
), Val_int(fd
), Val_int(type
));
138 caml_enter_blocking_section();
142 set_struct_timeval(struct timeval
*tv
, value vfloat
)
144 double timeout
= Double_val(vfloat
);
145 tv
->tv_sec
= (int) timeout
;
146 tv
->tv_usec
= (int) (1e6
* (timeout
- tv
->tv_sec
));
150 oc_create_event(value u
)
154 struct event
* ev
= caml_stat_alloc(sizeof(struct event
));
155 memset(ev
, 0, sizeof(*ev
));
157 ve
= caml_alloc_custom(&struct_event_ops
, sizeof(struct event
*), 0, 1);
158 struct_event_val(ve
) = ev
;
164 oc_event_id(value vevent
)
167 CAMLreturn(Val_long((long) struct_event_val(vevent
)));
171 oc_event_fd(value vevent
)
174 CAMLreturn(Val_long(EVENT_FD(struct_event_val(vevent
))));
178 oc_event_set(value vbase
, value vevent
, value fd
, value vevent_flag
)
180 CAMLparam4(vbase
, vevent
, fd
, vevent_flag
);
182 struct event
*event
= struct_event_val(vevent
);
183 struct event_base
* base
= get_struct_event_base_val(vbase
);
185 event_set(event
, Int_val(fd
), Int_val(vevent_flag
),
188 if (0 != event_base_set(base
, event
))
190 raise_error("event_set", "event_base_set");
193 CAMLreturn(Val_unit
);
197 oc_event_add(value vevent
, value vfloat_option
)
199 CAMLparam2(vevent
, vfloat_option
);
200 struct event
*event
= struct_event_val(vevent
);
201 struct timeval timeval
;
202 struct timeval
*tv
= NULL
;
204 if (Is_some(vfloat_option
)) {
205 set_struct_timeval(&timeval
, Field(vfloat_option
, 0));
209 if (0 != event_add(event
, tv
)) {
210 raise_error("event_add", "event_add");
213 CAMLreturn(Val_unit
);
217 oc_event_del(value vevent
)
220 struct event
*event
= struct_event_val(vevent
);
224 CAMLreturn(Val_unit
);
228 oc_event_pending(value vevent
, value vtype
)
230 CAMLparam2(vevent
, vtype
);
231 struct event
*event
= struct_event_val(vevent
);
234 r
= event_pending(event
, Int_val(vtype
), NULL
);
236 CAMLreturn(Val_bool(r
));
240 oc_event_active(value vevent
, value vtype
)
242 CAMLparam2(vevent
, vtype
);
243 struct event
*event
= struct_event_val(vevent
);
245 event_active(event
, Int_val(vtype
), 0);
247 CAMLreturn(Val_unit
);
251 oc_event_base_loop(value vbase
, value vloop_flag
)
253 CAMLparam2(vbase
,vloop_flag
);
254 struct event_base
* base
= get_struct_event_base_val(vbase
);
256 if (0 == Int_val(vloop_flag
)) flag
= EVLOOP_ONCE
;
257 else if (1 == Int_val(vloop_flag
)) flag
= EVLOOP_NONBLOCK
;
258 else caml_invalid_argument("loop");
260 caml_enter_blocking_section();
261 if((-1 == event_base_loop(base
,flag
))) {
262 caml_leave_blocking_section();
263 raise_error("event_loop", NULL
);
265 caml_leave_blocking_section();
267 CAMLreturn(Val_unit
);
272 oc_event_base_dispatch(value vbase
)
275 struct event_base
* base
= get_struct_event_base_val(vbase
);
277 caml_enter_blocking_section();
278 if((-1 == event_base_dispatch(base
))) {
279 caml_leave_blocking_section();
280 raise_error("event_dispatch", NULL
);
282 caml_leave_blocking_section();
284 CAMLreturn(Val_unit
);
288 * Initialize event base
291 oc_event_base_init(value unit
)
295 struct event_base
* base
= NULL
;
297 /* setup the event callback closure if needed */
298 if(event_cb_closure
== NULL
) {
299 event_cb_closure
= caml_named_value("event_cb");
300 if(event_cb_closure
== NULL
) {
301 invalid_argument("Callback event_cb not initialized.");
305 base
= event_base_new();
307 raise_error("event_base_init", NULL
);
310 v
= caml_alloc_custom(&struct_event_base_ops
, sizeof(struct event_base
*), 0, 1);
311 struct_event_base_val(v
) = base
;
317 oc_event_base_reinit(value vbase
)
320 struct event_base
* base
= get_struct_event_base_val(vbase
);
322 if (0 != event_reinit(base
)) {
323 raise_error("event_base_reinit", NULL
);
326 CAMLreturn(Val_unit
);
330 oc_event_base_free(value vbase
)
334 struct event_base
* base
= get_struct_event_base_val(vbase
);
335 event_base_free(base
);
336 struct_event_base_val(vbase
) = NULL
;
338 CAMLreturn(Val_unit
);