mirror of https://github.com/nealey/irc-bot
Some work on poll() compatibility layer.
This commit is contained in:
parent
c1d83191fe
commit
dd18d6ad48
|
@ -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,8 +387,9 @@ ocaml_epoll_wait(value t, value maxevents, value timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Val_int(0);
|
result = Val_int(0);
|
||||||
|
if (0 < ret) {
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i=0; ((i < t_->nfds) && (i < maxevents_)); i += 1) {
|
for (i = 0; ((i < t_->nfds) && (i < maxevents_)); i += 1) {
|
||||||
struct pollfd *p = &(t_->fds[i]);
|
struct pollfd *p = &(t_->fds[i]);
|
||||||
|
|
||||||
if (p->revents & POLLNVAL) {
|
if (p->revents & POLLNVAL) {
|
||||||
|
@ -405,11 +404,12 @@ ocaml_epoll_wait(value t, value maxevents, value timeout)
|
||||||
if (i != j) {
|
if (i != j) {
|
||||||
t_->fds[i] = t_->fds[j];
|
t_->fds[i] = t_->fds[j];
|
||||||
}
|
}
|
||||||
j += i;
|
j += 1;
|
||||||
}
|
}
|
||||||
t_->nfds = j;
|
t_->nfds = j;
|
||||||
|
}
|
||||||
CAMLreturn(result);
|
CAMLreturn(result);
|
||||||
|
#error "I haven't yet figured out why this causes a segfault."
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
91
tests.ml
91
tests.ml
|
@ -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 =
|
Epoll.ctl e Epoll.Add (a, [Epoll.Out; Epoll.In]);
|
||||||
assert_equal
|
assert_equal
|
||||||
~printer:epollfds_as_string
|
~printer:epollfds_as_string
|
||||||
(List.sort compare what)
|
[(a, [Epoll.Out])]
|
||||||
(List.sort compare (Epoll.wait e n 0))
|
(Epoll.wait e 1 0);
|
||||||
in
|
|
||||||
Epoll.ctl e Epoll.Add (a, [Epoll.Out; Epoll.In]);
|
|
||||||
expect [(a, [Epoll.Out])];
|
|
||||||
|
|
||||||
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:string_of_int
|
~printer:epollfds_as_string
|
||||||
1
|
[(a, [Epoll.Out]); (b, [Epoll.Out])]
|
||||||
(List.length (Epoll.wait e 1 0));
|
(Epoll.wait e 2 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,58 +85,23 @@ 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 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;
|
Epoll.destroy e;
|
||||||
|
Unix.close a
|
||||||
);
|
);
|
||||||
|
|
||||||
"command_of_string" >::
|
"command_of_string" >::
|
||||||
|
|
Loading…
Reference in New Issue