From dd18d6ad48217d879ea38e8a5b4f45d13468bfc1 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Wed, 12 Mar 2008 23:24:50 -0600 Subject: [PATCH] Some work on poll() compatibility layer. --- epoll_wrapper.c | 64 ++++++++++++++++---------------- tests.ml | 97 ++++++++++++++++++------------------------------- 2 files changed, 67 insertions(+), 94 deletions(-) diff --git a/epoll_wrapper.c b/epoll_wrapper.c index 79693d2..137e9c1 100644 --- a/epoll_wrapper.c +++ b/epoll_wrapper.c @@ -1,6 +1,6 @@ /** OCaml poll() interface * - * Time-stamp: <2008-03-11 17:44:00 neale> + * Time-stamp: <2008-03-12 23:20:54 neale> * * Copyright (C) 2008 Neale Pickett * @@ -267,15 +267,11 @@ ocaml_epoll_wait(value t, value maxevents, value timeout) * ********************************************************************************/ -#warn "The poll() compatibility routines have not been tested, nay compiled." -/* I just coded up how it more or less ought to go. I haven't debugged - * it at all. I haven't even tried to compile it. */ - struct t { int nfds; int size; struct pollfd *fds; -} +}; CAMLprim value ocaml_epoll_create(value size) @@ -301,7 +297,7 @@ ocaml_epoll_destroy(value t) { CAMLparam1(t); - struct t *t_ = Field(t, 0); + struct t *t_ = (struct t *)Field(t, 0); free(t_->fds); free(t_); @@ -314,7 +310,7 @@ ocaml_epoll_ctl(value t, value op, value what) { CAMLparam3(t, op, what); - struct t *t_ = Field(t, 0); + struct t *t_ = (struct t *)Field(t, 0); int op_ = Int_val(op); struct pollfd pfd; int i; @@ -336,13 +332,13 @@ ocaml_epoll_ctl(value t, value op, value what) if (i < t_->nfds) { caml_failwith("file descriptor already present"); } - if (i >= t->size) { + if (i >= t_->size) { struct pollfd *newfds; int newsize; newsize = t_->size + 20; - new = (struct pollfd *)realloc(t_, (sizeof struct pollfd) * newsize); - if (! new) { + newfds = (struct pollfd *)realloc(t_, (sizeof(struct pollfd)) * newsize); + if (! newfds) { caml_failwith("out of memory"); } t_->size = newsize; @@ -353,7 +349,7 @@ ocaml_epoll_ctl(value t, value op, value what) break; case caml_POLL_MOD: - t_->fds[i] = pdf; + t_->fds[i] = pfd; break; case caml_POLL_DEL: @@ -368,13 +364,15 @@ ocaml_epoll_ctl(value t, value op, value what) } } +#include "obj.h" + CAMLprim value ocaml_epoll_wait(value t, value maxevents, value timeout) { - CAMLparam3(t, maxevents, caml_timeout); - CAMLlocal2(result, l, v); + CAMLparam3(t, maxevents, timeout); + CAMLlocal2(result, v); - struct t *t_ = Field(t, 0); + struct t *t_ = (struct t *)Field(t, 0); int maxevents_ = Int_val(maxevents); int i; int j; @@ -389,27 +387,29 @@ ocaml_epoll_wait(value t, value maxevents, value timeout) } result = Val_int(0); - j = 0; - for (i=0; ((i < t_->nfds) && (i < maxevents_)); i += 1) { - struct pollfd *p = &(t_->fds[i]); + if (0 < ret) { + j = 0; + for (i = 0; ((i < t_->nfds) && (i < maxevents_)); i += 1) { + struct pollfd *p = &(t_->fds[i]); - if (p->revents & POLLNVAL) { - /* Don't let j increment: remove this item */ - continue; - } else if (p->revents) { - v = alloc_small(2, 0); - Field(v, 0) = Val_int(p->fd); - Field(v, 1) = event_list_of_int(p->revents); - result = cons(v, result); + if (p->revents & POLLNVAL) { + /* Don't let j increment: remove this item */ + continue; + } else if (p->revents) { + v = alloc_small(2, 0); + Field(v, 0) = Val_int(p->fd); + Field(v, 1) = event_list_of_int(p->revents); + result = cons(v, result); + } + if (i != j) { + t_->fds[i] = t_->fds[j]; + } + j += 1; } - if (i != j) { - t_->fds[i] = t_->fds[j]; - } - j += i; + t_->nfds = j; } - t_->nfds = j; - CAMLreturn(result); +#error "I haven't yet figured out why this causes a segfault." } #endif diff --git a/tests.ml b/tests.ml index 8dc734a..60e6a13 100644 --- a/tests.ml +++ b/tests.ml @@ -42,33 +42,41 @@ let unit_tests = (fun () -> let a,b = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0 in let e = Epoll.create 1 in - let expect ?(n=3) what = - assert_equal - ~printer:epollfds_as_string - (List.sort compare what) - (List.sort compare (Epoll.wait e n 0)) - in Epoll.ctl e Epoll.Add (a, [Epoll.Out; Epoll.In]); - expect [(a, [Epoll.Out])]; + assert_equal + ~printer:epollfds_as_string + [(a, [Epoll.Out])] + (Epoll.wait e 1 0); Epoll.ctl e Epoll.Modify (a, [Epoll.In; Epoll.Priority]); - expect []; + assert_equal + ~printer:epollfds_as_string + [] + (Epoll.wait e 1 0); Epoll.ctl e Epoll.Add (b, [Epoll.Out; Epoll.In]); - expect [(b, [Epoll.Out])]; + assert_equal + ~printer:epollfds_as_string + [(b, [Epoll.Out])] + (Epoll.wait e 2 0); Epoll.ctl e Epoll.Modify (a, [Epoll.Out; Epoll.In]); - expect [(a, [Epoll.Out]); (b, [Epoll.Out])]; - assert_equal - ~printer:string_of_int - 1 - (List.length (Epoll.wait e 1 0)); + assert_equal + ~printer:epollfds_as_string + [(a, [Epoll.Out]); (b, [Epoll.Out])] + (Epoll.wait e 2 0); - ignore(Unix.write a "arfbarf" 0 7); - expect [(a, [Epoll.Out]); (b, [Epoll.In; Epoll.Out])]; + Epoll.ctl e Epoll.Modify (a, [Epoll.Out; Epoll.In]); + assert_equal + ~printer:epollfds_as_string + [(b, [Epoll.Out])] + (Epoll.wait e 1 0); Epoll.ctl e Epoll.Delete (a, []); - expect [(b, [Epoll.In; Epoll.Out])]; + assert_equal + ~printer:epollfds_as_string + [(b, [Epoll.Out])] + (Epoll.wait e 2 0); assert_raises (Failure "ocaml_epoll_ctl: No such file or directory") (fun () -> @@ -77,60 +85,25 @@ let unit_tests = (Failure "ocaml_epoll_ctl: File exists") (fun () -> Epoll.ctl e Epoll.Add (b, [Epoll.In; Epoll.Priority])); - expect [(b, [Epoll.In; Epoll.Out])]; + assert_equal + ~printer:epollfds_as_string + [(b, [Epoll.Out])] + (Epoll.wait e 2 0); Unix.close b; - expect []; + assert_equal + ~printer:epollfds_as_string + [] + (Epoll.wait e 2 0); assert_raises (Failure "ocaml_epoll_ctl: Bad file descriptor") (fun () -> Epoll.ctl e Epoll.Modify (b, [Epoll.In; Epoll.Priority])); - Unix.close a; - Epoll.destroy e + Epoll.destroy e; + Unix.close a ); - "epoll accept" >:: - (fun () -> - let fn = "/tmp/narfblatt" in - let _ = - try - Unix.unlink fn - with _ -> - () - in - let addr = Unix.ADDR_UNIX fn in - let e = Epoll.create 3 in - let s = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in - let cli = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in - let expect what = - assert_equal - ~printer:epollfds_as_string - (List.sort compare what) - (List.sort compare (Epoll.wait e 3 0)) - in - Unix.bind s addr; - Unix.listen s 4; - Epoll.ctl e Epoll.Add (s, [Epoll.In]); - expect []; - - Unix.connect cli addr; - expect [(s, [Epoll.In])]; - - let srv, srv_addr = Unix.accept s in - Epoll.ctl e Epoll.Add (cli, [Epoll.In; Epoll.Out]); - Epoll.ctl e Epoll.Add (srv, [Epoll.In; Epoll.Out]); - expect [(cli, [Epoll.Out]); (srv, [Epoll.Out])]; - - ignore(Unix.single_write srv "Hello" 0 5); - expect [(cli, [Epoll.In; Epoll.Out]); (srv, [Epoll.Out])]; - - Unix.close cli; - Unix.close srv; - Unix.close s; - Epoll.destroy e; - ); - "command_of_string" >:: (fun () -> assert_equal