package uwt

  1. Overview
  2. Docs

Poll handles are used to watch file descriptors for readability, writability and disconnection similar to the purpose of poll(2).

The purpose of poll handles is to enable integrating external libraries that rely on the event loop to signal it about the socket status changes, like c-ares or libssh2. Using Poll.t for any other purpose is not recommended; Tcp.t, Udp.t, etc. provide an implementation that is faster and more scalable than what can be achieved with t, especially on Windows.

It is possible that poll handles occasionally signal that a file descriptor is readable or writable even when it isn't. The user should therefore always be prepared to handle EAGAIN or equivalent when it attempts to read from or write to the fd.

It is not okay to have multiple active poll handles for the same socket, this can cause libuv to busyloop or otherwise malfunction.

The user should not close a file descriptor while it is being polled by an active poll handle. This can cause the handle to report an error, but it might also start polling another socket. However the fd can be safely closed immediately after a call to close.

Note: On windows only sockets can be polled with poll handles. On Unix any file descriptor that would be accepted by poll(2) can be used.

Note: On AIX, watching for disconnection is not supported.

type t
include module type of Handle with type t := t
val close : t -> Int_result.unit

Handles are closed automatically, if they are not longer referenced from the OCaml heap. Nevertheless, you should nearly always close them with close, because:

  • if they wrap a file descriptor, you will sooner or later run out of file descriptors. The OCaml garbage collector doesn't give any guarantee, when orphaned memory blocks are removed.
  • you might have registered some repeatedly called action (e.g. timeout, read_start,...), that prevent that all references get removed from the OCaml heap.

However, it's safe to write code in this manner:

let s = Uwt.Tcp.init () in
let c = Uwt.Tcp.init () in
Uwt.Tcp.nodelay s false;
Uwt.Tcp.simultaneous_accepts true;
if foobar () then (* no file descriptor yet assigned, no need to worry
                     about exceptions inside foobar,... *)
  Lwt.return_unit (* no need to close *)
else
  ...

If you want - for whatever reason - keep a file descriptor open for the whole lifetime of your process, remember to keep a reference to its handle.

val close_noerr : t -> unit
val close_wait : t -> unit Lwt.t

Prefer close or close_noerr to close_wait. close or close_noerr return immediately (there are no useful error messages, beside perhaps a notice, that you've already closed that handle).

close_wait is only useful, if you intend to wait until all concurrent write and read threads related to this handle are canceled.

val is_active : t -> bool

Returns non-zero if the handle is active, zero if it's inactive. What "active" means depends on the type of handle:

  • A Async.t handle is always active and cannot be deactivated, except by closing it with uv_close().
  • A Pipe.t, Tcp.t, Udp.t, etc. handle - basically any handle that deals with i/o - is active when it is doing something that involves i/o, like reading, writing, connecting, accepting new connections, etc.

Rule of thumb: if a handle of type Uwt.Foo.t has a uv_foo_start() function, then it's active from the moment that function is called. Likewise, uv_foo_stop() deactivates the handle again.

val ref' : t -> unit

Reference the given handle. References are idempotent, that is, if a handle is already referenced calling this function again will have no effect.

val unref : t -> unit

Un-reference the given handle. References are idempotent, that is, if a handle is not referenced calling this function again will have no effect.

val has_ref : t -> bool

Returns non-zero if the handle is referenced, zero otherwise.

include module type of Handle_fileno with type t := t
val fileno : t -> Unix.file_descr uv_result
val fileno_exn : t -> Unix.file_descr
val to_handle : t -> Handle.t
type event =
  1. | Readable
  2. | Writable
  3. | Disconnect
  4. | Prioritized
val start : Unix.file_descr -> event list -> cb:(t -> event list uv_result -> unit) -> t uv_result

Starts polling the file descriptor. events is a list of Readable, Writable and Disconnect. As soon as an event is detected the callback will be called with status set to 0, and the detected events set on the events field.

The Disconnect event is optional in the sense that it may not be reported and the user is free to ignore it, but it can help optimize the shutdown path because an extra read or write call might be avoided.

val start_exn : Unix.file_descr -> event list -> cb:(t -> event list uv_result -> unit) -> t
val update_events : t -> event list -> Int_result.unit

Update the events mask that is being watched for

val update_events_exn : t -> event list -> unit