module Ev:Ev is a module for binding libev, which is a high-performance event loop. You may wish to browse libev's documentation from time to time, but this documentation attempts to be as self-containing API documentation as possible, with links to relevant libev's documentation where appropriate.sig
..end
typeloop_flag =
[ `FORKCHECK | `NOENV ]
type
run_loop_flag =
| |
OneShot |
| |
NonBlock |
typebackend =
[ `DEVPOLL | `EPOLL | `KQUEUE | `POLL | `PORT | `SELECT ]
typeloop_arg =
[ `DEVPOLL | `EPOLL | `FORKCHECK | `KQUEUE | `NOENV | `POLL | `PORT | `SELECT ]
type
unloop_how =
| |
UnloopOne |
(* | unloop the innermost loop | *) |
| |
UnloopAll |
(* | unloop all loops | *) |
type
revent =
| |
READ |
(* | ev_io detected read will not block | *) |
| |
WRITE |
(* | ev_io detected write will not block | *) |
| |
IOFDSET |
(* | internal use only | *) |
| |
TIMEOUT |
(* | timer timed out | *) |
| |
PERIODIC |
(* | periodic timer timed out | *) |
| |
SIGNAL |
(* | signal was received | *) |
| |
CHILD |
(* | child/pid had status change | *) |
| |
STAT |
(* | stat data changed | *) |
| |
IDLE |
(* | event loop is idling | *) |
| |
PREPARE |
(* | event loop about to poll | *) |
| |
CHECK |
(* | event loop finished poll | *) |
| |
EMBED |
(* | embedded event loop needs sweep | *) |
| |
FORK |
(* | event loop resumed in child | *) |
| |
ERROR |
(* | sent when an error occurs | *) |
exception NoLoop
exception LoopInitFailed
exception VersionMismatch
exception StaleObject
typerevents =
revent list
type
loop
type 'a
ev
type'a
cb ='a ev -> revents -> unit
typeexn_handler =
loop -> exn -> unit
val string_of_loop_arg : [< loop_arg ] -> string
val string_of_revent : revent -> string
val embeddable_backends : unit -> backend list
val supported_backends : unit -> backend list
val recommended_backends : unit -> backend list
val default_loop : loop_arg list -> loop
LoopInitFailed
if the initialization failedVersionMismatch
if the system library is too old compared to the library this wrapper was compiled againstval loop_new : loop_arg list -> loop
LoopInitFailed
if the initialization of the loop failedVersionMismatch
if the system library is too old compared to the library this wrapper was compiled againstval loop_destroy : loop -> unit
val loop_now : loop -> float
val is_default_loop : loop -> bool
val loop_count : loop -> int
val loop : loop -> run_loop_flag list -> unit
val unloop : loop -> unloop_how -> unit
val set_exn_handler : loop -> exn_handler -> unit
val default_exn_handler : loop -> exn -> unit
val forked : loop -> unit
val set_io_collect_interval : loop -> float -> unit
val set_timeout_collect_interval : loop -> float -> unit
val set_cb : 'a ev -> 'a cb -> unit
val get_cb : 'a ev -> 'a cb
val no_cb : 'a cb
val is_active : 'a ev -> bool
val is_pending : 'a ev -> bool
val get_priority : 'a ev -> int
val set_priority : 'a ev -> int -> unit
val set_keepalive : 'a ev -> bool -> unit
val get_loop : 'a ev -> loop
val invoke : 'a ev -> revents -> unit
NoLoop
if the event is not activeval clear_pending : 'a ev -> revents
val start : loop -> 'a ev -> unit
Invalid_argument
the event loop is started to another loopval stop : 'a ev -> unit
Libev documentation: Libev ev_io
type
io
val io_init : Unix.file_descr -> revents -> io cb -> io ev
Libev documention: Libev ev_timer
type
timer
val timer_init : float -> float -> timer cb -> timer ev
val timer_again : timer ev -> unit
NoLoop
if this event is not active
Libev documention: Libev ev_periodic
type
periodic
typereschedule_cb =
periodic ev -> float -> float
type
periodic_time =
| |
Absolute of |
(* | absolute unix time | *) |
| |
Repeating of |
(* | offset * interval - repeat every interval seconds, with unix time offset offset | *) |
| |
Manual of |
(* | use a custom rescheduling function | *) |
val periodic_init : periodic_time -> periodic cb -> periodic ev
val periodic_set : periodic ev -> periodic_time -> unit
val periodic_get_at : periodic ev -> float
Libev documention: Libev ev_signal
type
signal
val signal_init : int -> signal cb -> signal ev
Libev documention: Libev ev_child
type
child
val child_init : int -> bool -> child cb -> child ev
val child_set : child ev -> int -> bool -> unit
val child_get_pid : child ev -> int
val child_get_rpid : child ev -> int
val child_get_rstatus : child ev -> int
Libev documentation: Libev ev_stat
type
stat
val stat_init : string -> float -> stat cb -> stat ev
val stat_set : stat ev -> string -> float -> unit
val stat_get_attr : stat ev -> Unix.stats
val stat_get_prev : stat ev -> Unix.stats
Libev documentation: Libev ev_idle
type
idle
val idle_init : idle cb -> idle ev
Libev documentation: Libev ev_fork
type
fork
val fork_init : fork cb -> fork ev
Libev documention: Libev ev_prepare/check
type
prepare
type
check
val prepare_init : prepare cb -> prepare ev
val check_init : check cb -> check ev
A complete example of semi-efficiently receiving data from stdin and timing out when there has not been input for a short interval (5 seconds).
For some reason this example can misbehave when copy-pasted to a toplevel. #use works fine, though. The problem is that the timeout is fired either instantaneously or otherwise too fast (in about 3 seconds).
(* function for feeding strings to buffer and retrieving whole lines *)
let add_buf_str buf str length =
let rec add_buf_at buf ofs =
let rec find_eol at =
if at < length then
if str.[at] = '\n' then
Some at
else
find_eol (at + 1)
else
None
in
match find_eol ofs with
| None ->
if length <> ofs then
Buffer.add_substring buf str ofs (length - ofs);
[]
| Some at ->
Buffer.add_substring buf str ofs (at - ofs);
let str = Buffer.contents buf in
Buffer.clear buf;
str::add_buf_at buf (at + 1)
in
add_buf_at buf 0
let main () =
(* the default event loop *)
let loop = Ev.default_loop [] in
(* intermediate storage for incoming bytes *)
let buf = Buffer.create 1024 in
let exit_io io =
Printf.printf "Bye!\n%!";
Ev.stop io
in
(* a receiving buffer for a single message *)
let str_buf = String.create 1024 in
(* start io immediately after creating it *)
let io_wait = Ev.io_init Unix.stdin [Ev.READ] Ev.no_cb in
let timeout_wait = Ev.timer_init 5.0 5.0 Ev.no_cb in
Ev.set_cb io_wait (
(* use io parameter for an easy mechanism to stop itself *)
(* revents parameter is ignored *)
fun io _ ->
(* receive data from the peer.. (stdin in this case) *)
try
let n = Unix.read Unix.stdin str_buf 0 (String.length str_buf) in
(* bail out when there is an EOF or an error (doesn't handle EAGAIN) *)
if n <= 0 then exit_io io
else
((* reset timer *)
Ev.timer_again timeout_wait;
(* output received messages *)
List.iter
(fun str ->
Printf.printf "Received: %s\n%!" str;
if str = "bye" then
begin
Ev.stop io;
Ev.stop timeout_wait;
end
)
(add_buf_str buf str_buf n)
)
with
| Unix.Unix_error ((Unix.EAGAIN | Unix.EINTR), _, _) -> ()
| Unix.Unix_error _ -> exit_io io
);
Ev.set_cb timeout_wait (
fun io revents ->
Printf.printf "Timeout! %s\n%!" (String.concat " " (List.map Ev.string_of_revent revents));
Ev.unloop (Ev.get_loop io) Ev.UnloopOne;
);
Ev.start loop io_wait;
Ev.start loop timeout_wait;
(* set the descriptor to a non-blocking mode just in case (certain platforms may produce
spurious events) *)
Unix.set_nonblock Unix.stdin;
(* start it! *)
Ev.loop loop [];
Unix.clear_nonblock Unix.stdin
let () = main ()