mirror of https://github.com/nealey/irc-bot
Experimental work on an OCaml poll() wrapper
This commit is contained in:
parent
babb102cd4
commit
d9b83175a2
12
OMakefile
12
OMakefile
|
@ -1,16 +1,18 @@
|
||||||
USE_OCAMLFIND = true
|
|
||||||
OCAMLPACKS[] =
|
OCAMLPACKS[] =
|
||||||
equeue
|
equeue
|
||||||
pcre
|
pcre
|
||||||
str
|
str
|
||||||
NATIVE_ENABLED = true
|
|
||||||
BYTE_ENABLED = true
|
|
||||||
OCAMLCFLAGS += -g
|
OCAMLCFLAGS += -g
|
||||||
|
|
||||||
.DEFAULT: ircd
|
.DEFAULT: ircd
|
||||||
|
|
||||||
OCamlProgram(ircd, ircd irc command iobuf client channel)
|
OCamlProgram(ircd, ircd irc command iobuf client channel)
|
||||||
|
|
||||||
|
section
|
||||||
|
OCAML_CLIBS = ocamlpoll
|
||||||
|
StaticCLibrary(ocamlpoll, inspect poll_stubs)
|
||||||
|
OCamlProgram(polltest, polltest)
|
||||||
|
|
||||||
section
|
section
|
||||||
OCAMLPACKS[] +=
|
OCAMLPACKS[] +=
|
||||||
oUnit
|
oUnit
|
||||||
|
@ -23,6 +25,10 @@ section
|
||||||
|
|
||||||
OCamlProgram(tests, tests chat irc command iobuf client channel)
|
OCamlProgram(tests, tests chat irc command iobuf client channel)
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: tests
|
||||||
|
./tests
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm $(filter-proper-targets $(ls R, .))
|
rm $(filter-proper-targets $(ls R, .))
|
||||||
|
|
38
OMakeroot
38
OMakeroot
|
@ -1,37 +1,9 @@
|
||||||
########################################################################
|
open build/C
|
||||||
# Permission is hereby granted, free of charge, to any person
|
|
||||||
# obtaining a copy of this file, to deal in the File without
|
|
||||||
# restriction, including without limitation the rights to use,
|
|
||||||
# copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
# sell copies of the File, and to permit persons to whom the
|
|
||||||
# File is furnished to do so, subject to the following condition:
|
|
||||||
#
|
|
||||||
# THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE FILE OR
|
|
||||||
# THE USE OR OTHER DEALINGS IN THE FILE.
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
# The standard OMakeroot file.
|
|
||||||
# You will not normally need to modify this file.
|
|
||||||
# By default, your changes should be placed in the
|
|
||||||
# OMakefile in this directory.
|
|
||||||
#
|
|
||||||
# If you decide to modify this file, note that it uses exactly
|
|
||||||
# the same syntax as the OMakefile.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Include the standard installed configuration files.
|
|
||||||
# Any of these can be deleted if you are not using them,
|
|
||||||
# but you probably want to keep the Common file.
|
|
||||||
#
|
|
||||||
#open build/C
|
|
||||||
open build/OCaml
|
open build/OCaml
|
||||||
#open build/LaTeX
|
|
||||||
|
USE_OCAMLFIND = true
|
||||||
|
NATIVE_ENABLED = true
|
||||||
|
BYTE_ENABLED = true
|
||||||
|
|
||||||
#
|
#
|
||||||
# The command-line variables are defined *after* the
|
# The command-line variables are defined *after* the
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <caml/mlvalues.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
margin (int n)
|
||||||
|
{
|
||||||
|
while (n-- > 0)
|
||||||
|
printf(".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_block(value v,int m)
|
||||||
|
{
|
||||||
|
int size, i;
|
||||||
|
margin(m);
|
||||||
|
if (Is_long(v))
|
||||||
|
{ printf("immediate value (%d)\n", Long_val(v)); return; };
|
||||||
|
printf ("memory block: size=%d - ", size=Wosize_val(v));
|
||||||
|
switch (Tag_val(v))
|
||||||
|
{
|
||||||
|
case Closure_tag :
|
||||||
|
printf("closure with %d free variables\n", size-1);
|
||||||
|
margin(m+4); printf("code pointer: %p\n",Code_val(v)) ;
|
||||||
|
for (i=1;i<size;i++) print_block(Field(v,i), m+4);
|
||||||
|
break;
|
||||||
|
case String_tag :
|
||||||
|
printf("string: %s (%s)\n", String_val(v),(char *) v);
|
||||||
|
break;
|
||||||
|
case Double_tag:
|
||||||
|
printf("float: %g\n", Double_val(v));
|
||||||
|
break;
|
||||||
|
case Double_array_tag :
|
||||||
|
printf ("float array: ");
|
||||||
|
for (i=0;i<size/Double_wosize;i++) printf(" %g", Double_field(v,i));
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
case Abstract_tag : printf("abstract type\n"); break;
|
||||||
|
default:
|
||||||
|
if (Tag_val(v)>=No_scan_tag) { printf("unknown tag"); break; };
|
||||||
|
printf("structured block (tag=%d):\n",Tag_val(v));
|
||||||
|
for (i=0;i<size;i++) print_block(Field(v,i),m+4);
|
||||||
|
}
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
value
|
||||||
|
inspect_block (value v)
|
||||||
|
{
|
||||||
|
print_block(v,4);
|
||||||
|
fflush(stdout);
|
||||||
|
return v;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
type pollfd = {fd: int;
|
||||||
|
events: int;
|
||||||
|
revents: int}
|
||||||
|
|
||||||
|
external in : int = "poll_in"
|
|
@ -0,0 +1,150 @@
|
||||||
|
#include <caml/mlvalues.h>
|
||||||
|
#include <caml/fail.h>
|
||||||
|
#include <caml/custom.h>
|
||||||
|
#include <caml/memory.h>
|
||||||
|
#include <caml/alloc.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define puke(str) \
|
||||||
|
{ \
|
||||||
|
char errstr[512]; \
|
||||||
|
snprintf(errstr, sizeof(errstr), str ": %s", strerror(errno)); \
|
||||||
|
caml_failwith(errstr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
value inspect_block(value v);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
caml_POLLIN,
|
||||||
|
caml_POLLPRI,
|
||||||
|
caml_POLLOUT,
|
||||||
|
caml_POLLERR,
|
||||||
|
caml_POLLHUP,
|
||||||
|
caml_POLLNVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
list_length(value list)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
value l;
|
||||||
|
|
||||||
|
for (l = list; l != Val_int(0); l = Field(l, 1)) {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
int_of_event_list(value list)
|
||||||
|
{
|
||||||
|
int acc = 0;
|
||||||
|
value l;
|
||||||
|
|
||||||
|
for (l = list; l != Val_int(0); l = Field(l, 1)) {
|
||||||
|
switch (Field(l, 0)) {
|
||||||
|
case caml_POLLIN:
|
||||||
|
acc |= POLLIN;
|
||||||
|
break;
|
||||||
|
case caml_POLLPRI:
|
||||||
|
acc |= POLLPRI;
|
||||||
|
break;
|
||||||
|
case caml_POLLOUT:
|
||||||
|
acc |= POLLOUT;
|
||||||
|
break;
|
||||||
|
case caml_POLLERR:
|
||||||
|
acc |= POLLERR;
|
||||||
|
break;
|
||||||
|
case caml_POLLHUP:
|
||||||
|
acc |= POLLHUP;
|
||||||
|
break;
|
||||||
|
case caml_POLLNVAL:
|
||||||
|
acc |= POLLNVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static value
|
||||||
|
append(value list, value item)
|
||||||
|
{
|
||||||
|
value new = alloc_small(2, 0);
|
||||||
|
Field(new, 0) = item;
|
||||||
|
Field(new, 1) = list;
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static value
|
||||||
|
event_list_of_int(int events)
|
||||||
|
{
|
||||||
|
value result = Val_int(0);
|
||||||
|
|
||||||
|
if (events & POLLIN) {
|
||||||
|
result = append(result, Val_int(caml_POLLIN));
|
||||||
|
} else if (events & POLLPRI) {
|
||||||
|
result = append(result, Val_int(caml_POLLPRI));
|
||||||
|
} else if (events & POLLOUT) {
|
||||||
|
result = append(result, Val_int(caml_POLLOUT));
|
||||||
|
} else if (events & POLLERR) {
|
||||||
|
result = append(result, Val_int(caml_POLLERR));
|
||||||
|
} else if (events & POLLHUP) {
|
||||||
|
result = append(result, Val_int(caml_POLLHUP));
|
||||||
|
} else if (events & POLLNVAL) {
|
||||||
|
result = append(result, Val_int(caml_POLLNVAL));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAMLprim value
|
||||||
|
ocaml_poll(value caml_fds, value caml_timeout)
|
||||||
|
{
|
||||||
|
CAMLparam2(caml_fds, caml_timeout);
|
||||||
|
CAMLlocal1(result);
|
||||||
|
|
||||||
|
value l;
|
||||||
|
int nfds;
|
||||||
|
int timeout = Int_val(caml_timeout);
|
||||||
|
struct pollfd fds[nfds];
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
result = Val_int(0);
|
||||||
|
inspect_block(caml_fds);
|
||||||
|
|
||||||
|
/* Count entries */
|
||||||
|
nfds = list_length(caml_fds);
|
||||||
|
|
||||||
|
/* Build fds */
|
||||||
|
for (i=0, l = caml_fds; l != Val_int(0); i += 1, l = Field(l, 1)) {
|
||||||
|
value f = Field(l, 0);
|
||||||
|
struct pollfd *p = &(fds[i]);
|
||||||
|
|
||||||
|
p->fd = Int_val(Field(f, 0));
|
||||||
|
p->events = int_of_event_list(Field(f, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call poll */
|
||||||
|
ret = poll(*fds, nfds, timeout);
|
||||||
|
if (-1 == ret) {
|
||||||
|
puke("poll");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i < nfds; i += 1) {
|
||||||
|
struct pollfd *p = &(fds[i]);
|
||||||
|
if (p->revents) {
|
||||||
|
value v = alloc_small(2,0);
|
||||||
|
|
||||||
|
Field(v, 0) = Val_int(p->fd);
|
||||||
|
Field(v, 1) = event_list_of_int(p->revents);
|
||||||
|
result = append(result, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CAMLreturn(result);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
external poll : 'a -> 'b -> 'c = "ocaml_poll"
|
||||||
|
|
||||||
|
type event = POLLIN | POLLPRI | POLLOUT | POLLERR | POLLHUP | POLLNVAL
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
poll [
|
||||||
|
(10, [POLLIN; POLLOUT]);
|
||||||
|
(20, [POLLOUT])
|
||||||
|
] ()
|
Loading…
Reference in New Issue