Some work on poll() compatibility layer.

This commit is contained in:
Neale Pickett 2008-03-12 23:24:50 -06:00
parent c1d83191fe
commit dd18d6ad48
2 changed files with 67 additions and 94 deletions

View File

@ -1,6 +1,6 @@
/** OCaml poll() interface /** 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 * 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 { struct t {
int nfds; int nfds;
int size; int size;
struct pollfd *fds; struct pollfd *fds;
} };
CAMLprim value CAMLprim value
ocaml_epoll_create(value size) ocaml_epoll_create(value size)
@ -301,7 +297,7 @@ ocaml_epoll_destroy(value t)
{ {
CAMLparam1(t); CAMLparam1(t);
struct t *t_ = Field(t, 0); struct t *t_ = (struct t *)Field(t, 0);
free(t_->fds); free(t_->fds);
free(t_); free(t_);
@ -314,7 +310,7 @@ ocaml_epoll_ctl(value t, value op, value what)
{ {
CAMLparam3(t, op, what); CAMLparam3(t, op, what);
struct t *t_ = Field(t, 0); struct t *t_ = (struct t *)Field(t, 0);
int op_ = Int_val(op); int op_ = Int_val(op);
struct pollfd pfd; struct pollfd pfd;
int i; int i;
@ -336,13 +332,13 @@ ocaml_epoll_ctl(value t, value op, value what)
if (i < t_->nfds) { if (i < t_->nfds) {
caml_failwith("file descriptor already present"); caml_failwith("file descriptor already present");
} }
if (i >= t->size) { if (i >= t_->size) {
struct pollfd *newfds; struct pollfd *newfds;
int newsize; int newsize;
newsize = t_->size + 20; newsize = t_->size + 20;
new = (struct pollfd *)realloc(t_, (sizeof struct pollfd) * newsize); newfds = (struct pollfd *)realloc(t_, (sizeof(struct pollfd)) * newsize);
if (! new) { if (! newfds) {
caml_failwith("out of memory"); caml_failwith("out of memory");
} }
t_->size = newsize; t_->size = newsize;
@ -353,7 +349,7 @@ ocaml_epoll_ctl(value t, value op, value what)
break; break;
case caml_POLL_MOD: case caml_POLL_MOD:
t_->fds[i] = pdf; t_->fds[i] = pfd;
break; break;
case caml_POLL_DEL: case caml_POLL_DEL:
@ -368,13 +364,15 @@ ocaml_epoll_ctl(value t, value op, value what)
} }
} }
#include "obj.h"
CAMLprim value CAMLprim value
ocaml_epoll_wait(value t, value maxevents, value timeout) ocaml_epoll_wait(value t, value maxevents, value timeout)
{ {
CAMLparam3(t, maxevents, caml_timeout); CAMLparam3(t, maxevents, timeout);
CAMLlocal2(result, l, v); CAMLlocal2(result, v);
struct t *t_ = Field(t, 0); struct t *t_ = (struct t *)Field(t, 0);
int maxevents_ = Int_val(maxevents); int maxevents_ = Int_val(maxevents);
int i; int i;
int j; int j;
@ -389,27 +387,29 @@ ocaml_epoll_wait(value t, value maxevents, value timeout)
} }
result = Val_int(0); result = Val_int(0);
j = 0; if (0 < ret) {
for (i=0; ((i < t_->nfds) && (i < maxevents_)); i += 1) { j = 0;
struct pollfd *p = &(t_->fds[i]); for (i = 0; ((i < t_->nfds) && (i < maxevents_)); i += 1) {
struct pollfd *p = &(t_->fds[i]);
if (p->revents & POLLNVAL) { if (p->revents & POLLNVAL) {
/* Don't let j increment: remove this item */ /* Don't let j increment: remove this item */
continue; continue;
} else if (p->revents) { } else if (p->revents) {
v = alloc_small(2, 0); v = alloc_small(2, 0);
Field(v, 0) = Val_int(p->fd); Field(v, 0) = Val_int(p->fd);
Field(v, 1) = event_list_of_int(p->revents); Field(v, 1) = event_list_of_int(p->revents);
result = cons(v, result); result = cons(v, result);
}
if (i != j) {
t_->fds[i] = t_->fds[j];
}
j += 1;
} }
if (i != j) { t_->nfds = j;
t_->fds[i] = t_->fds[j];
}
j += i;
} }
t_->nfds = j;
CAMLreturn(result); CAMLreturn(result);
#error "I haven't yet figured out why this causes a segfault."
} }
#endif #endif

View File

@ -42,33 +42,41 @@ let unit_tests =
(fun () -> (fun () ->
let a,b = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0 in let a,b = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0 in
let e = Epoll.create 1 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]); 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]); 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]); 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]); Epoll.ctl e Epoll.Modify (a, [Epoll.Out; Epoll.In]);
expect [(a, [Epoll.Out]); (b, [Epoll.Out])]; assert_equal
assert_equal ~printer:epollfds_as_string
~printer:string_of_int [(a, [Epoll.Out]); (b, [Epoll.Out])]
1 (Epoll.wait e 2 0);
(List.length (Epoll.wait e 1 0));
ignore(Unix.write a "arfbarf" 0 7); Epoll.ctl e Epoll.Modify (a, [Epoll.Out; Epoll.In]);
expect [(a, [Epoll.Out]); (b, [Epoll.In; Epoll.Out])]; assert_equal
~printer:epollfds_as_string
[(b, [Epoll.Out])]
(Epoll.wait e 1 0);
Epoll.ctl e Epoll.Delete (a, []); 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 assert_raises
(Failure "ocaml_epoll_ctl: No such file or directory") (Failure "ocaml_epoll_ctl: No such file or directory")
(fun () -> (fun () ->
@ -77,60 +85,25 @@ let unit_tests =
(Failure "ocaml_epoll_ctl: File exists") (Failure "ocaml_epoll_ctl: File exists")
(fun () -> (fun () ->
Epoll.ctl e Epoll.Add (b, [Epoll.In; Epoll.Priority])); 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; Unix.close b;
expect []; assert_equal
~printer:epollfds_as_string
[]
(Epoll.wait e 2 0);
assert_raises assert_raises
(Failure "ocaml_epoll_ctl: Bad file descriptor") (Failure "ocaml_epoll_ctl: Bad file descriptor")
(fun () -> (fun () ->
Epoll.ctl e Epoll.Modify (b, [Epoll.In; Epoll.Priority])); 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" >:: "command_of_string" >::
(fun () -> (fun () ->
assert_equal assert_equal