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 | | | OneShot | 
| | | NonBlock | 
typebackend =[ `DEVPOLL | `EPOLL | `KQUEUE | `POLL | `PORT | `SELECT ]
typeloop_arg =[ `DEVPOLL | `EPOLL | `FORKCHECK | `KQUEUE | `NOENV | `POLL | `PORT | `SELECT ]
type | | | UnloopOne | (* | unloop the innermost loop | *) | 
| | | UnloopAll | (* | unloop all loops | *) | 
type | | | 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 
type 'a ev 
type'acb ='a ev -> revents -> unit
typeexn_handler =loop -> exn -> unit
val string_of_loop_arg : [< loop_arg ] -> stringval string_of_revent : revent -> stringval embeddable_backends : unit -> backend listval supported_backends : unit -> backend list
val recommended_backends : unit -> backend listval default_loop : loop_arg list -> loopLoopInitFailed 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 -> loopLoopInitFailed 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 -> unitval loop_now : loop -> float
val is_default_loop : loop -> boolval loop_count : loop -> intval loop : loop -> run_loop_flag list -> unitval unloop : loop -> unloop_how -> unitval set_exn_handler : loop -> exn_handler -> unitval default_exn_handler : loop -> exn -> unitval forked : loop -> unitval set_io_collect_interval : loop -> float -> unitval set_timeout_collect_interval : loop -> float -> unitval set_cb : 'a ev -> 'a cb -> unitval get_cb : 'a ev -> 'a cbval no_cb : 'a cbval is_active : 'a ev -> boolval is_pending : 'a ev -> boolval get_priority : 'a ev -> intval set_priority : 'a ev -> int -> unitval set_keepalive : 'a ev -> bool -> unitval get_loop : 'a ev -> loop
val invoke : 'a ev -> revents -> unitNoLoop if the event is not activeval clear_pending : 'a ev -> reventsval start : loop -> 'a ev -> unitInvalid_argument the event loop is started to another loopval stop : 'a ev -> unit
    Libev documentation: Libev ev_io
type 
val io_init : Unix.file_descr -> revents -> io cb -> io ev
    Libev documention: Libev ev_timer
type 
val timer_init : float -> float -> timer cb -> timer evval timer_again : timer ev -> unitNoLoop if this event is not active
    Libev documention: Libev ev_periodic
type 
typereschedule_cb =periodic ev -> float -> float
type | | | 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 evval periodic_set : periodic ev -> periodic_time -> unit
val periodic_get_at : periodic ev -> float
    Libev documention: Libev ev_signal
type 
val signal_init : int -> signal cb -> signal ev
    Libev documention: Libev ev_child
type 
val child_init : int -> bool -> child cb -> child evval child_set : child ev -> int -> bool -> unit
val child_get_pid : child ev -> intval child_get_rpid : child ev -> intval child_get_rstatus : child ev -> int
    Libev documentation: Libev ev_stat
type 
val stat_init : string -> float -> stat cb -> stat evval stat_set : stat ev -> string -> float -> unitval stat_get_attr : stat ev -> Unix.statsval stat_get_prev : stat ev -> Unix.stats
    Libev documentation: Libev ev_idle
type 
val idle_init : idle cb -> idle ev
    Libev documentation: Libev ev_fork
type 
val fork_init : fork cb -> fork ev
    Libev documention: Libev ev_prepare/check
type 
type 
val prepare_init : prepare cb -> prepare evval check_init : check cb -> check evA 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 ()