Skip to content

Commit

Permalink
Add Lwt_unix.IO_vectors.is_empty
Browse files Browse the repository at this point in the history
  • Loading branch information
aantron committed Nov 28, 2016
1 parent f9690b0 commit b6d1f9f
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
9 changes: 9 additions & 0 deletions src/unix/lwt_unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,15 @@ struct
in
io_vectors.prefix <- loop count io_vectors.prefix

let is_empty io_vectors =
_flatten io_vectors;
let rec loop = function
| [] -> true
| {length = 0; _}::rest -> loop rest
| _ -> false
in
loop io_vectors.prefix

external _stub_iov_max : unit -> int = "lwt_unix_iov_max"

let system_limit =
Expand Down
14 changes: 13 additions & 1 deletion src/unix/lwt_unix.mli
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,10 @@ sig
(** [drop vs n] adjusts the I/O vector sequence [vs] so that it no longer
includes its first [n] bytes. *)

val is_empty : t -> bool
(** [is_empty vs] is [true] if and only if [vs] has no I/O vectors, or all I/O
vectors in [vs] have zero bytes. *)

val system_limit : int option
(** Some systems limit the number of I/O vectors that can be passed in a
single call to their [writev] or [readv] system calls. On those systems,
Expand Down Expand Up @@ -445,7 +449,15 @@ val writev : file_descr -> IO_vectors.t -> int Lwt.t
underlying [writev] system call.
Not implemented on Windows. It should be possible to implement, upon
request, for Windows sockets only. *)
request, for Windows sockets only.
The behavior of [writev] when [vs] has zero slices depends on the system,
and may change in future versions of Lwt. On Linux, [writev] will succeed
and write zero bytes. On BSD (including macOS), [writev] will fail with
[Unix.Unix_error (Unix.EINVAL, "writev", ...)].
See {{:http://man7.org/linux/man-pages/man3/writev.3p.html}
[writev(3p)]}. *)

val readable : file_descr -> bool
(** Returns whether the given file descriptor is currently
Expand Down
51 changes: 45 additions & 6 deletions tests/unix/test_lwt_unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ let writev_tests =
Lwt.return (bytes_written = data_length && blocking_matches)
in

let reader read_fd expected_data = fun () ->
if expected_data = "" then
let reader read_fd ?(not_readable = false) expected_data = fun () ->
if not_readable then
let readable = Lwt_unix.readable read_fd in
Lwt_unix.close read_fd >>= fun () ->
Lwt.return (not readable)
Expand Down Expand Up @@ -285,7 +285,7 @@ let writev_tests =
[writer write_fd io_vectors 4;
reader read_fd "ooar"]);

test "writev: drop" ~only_if:(fun () -> not Sys.win32)
test "writev: drop, is_empty" ~only_if:(fun () -> not Sys.win32)
(fun () ->
let io_vectors =
make_io_vectors
Expand All @@ -296,11 +296,46 @@ let writev_tests =

let read_fd, write_fd = Lwt_unix.pipe () in

let initially_empty = Lwt_unix.IO_vectors.is_empty io_vectors in

Lwt_unix.IO_vectors.drop io_vectors 4;
let empty_after_partial_drop =
Lwt_unix.IO_vectors.is_empty io_vectors in

Lwt_list.for_all_s (fun t -> t ())
[writer write_fd io_vectors 5;
reader read_fd "arbaz"]);
reader read_fd "arbaz"] >>= fun io_correct ->

Lwt_unix.IO_vectors.drop io_vectors 5;
let empty_after_exact_drop = Lwt_unix.IO_vectors.is_empty io_vectors in

Lwt_unix.IO_vectors.drop io_vectors 100;
let empty_after_excess_drop = Lwt_unix.IO_vectors.is_empty io_vectors in

Lwt.return
(not initially_empty &&
not empty_after_partial_drop &&
io_correct &&
empty_after_exact_drop &&
empty_after_excess_drop));

test "writev: degenerate vectors" ~only_if:(fun () -> not Sys.win32)
(fun () ->
let io_vectors =
make_io_vectors
[`Bytes ("foo", 0, 0);
`Bigarray ("bar", 0, 0)]
in

let read_fd, write_fd = Lwt_unix.pipe () in

let initially_empty = Lwt_unix.IO_vectors.is_empty io_vectors in

Lwt_list.for_all_s (fun t -> t ())
[writer write_fd io_vectors 0;
reader read_fd ""] >>= fun io_correct ->

Lwt.return (initially_empty && io_correct));

test "writev: bad iovec" ~only_if:(fun () -> not Sys.win32)
(fun () ->
Expand Down Expand Up @@ -335,7 +370,7 @@ let writev_tests =
writer negative_offset';
writer negative_length';
writer out_of_bounds';
reader read_fd "";
reader read_fd ~not_readable:true "";
close write_fd]);

test "writev: iovecs exceeding limit"
Expand Down Expand Up @@ -375,7 +410,11 @@ let writev_tests =

Lwt_list.for_all_s (fun t -> t ())
[writer write_fd io_vectors 3;
reader read_fd "foo"]);
reader read_fd "foo"] >>= fun io_correct ->

Lwt.return
(io_correct &&
not (Lwt_unix.IO_vectors.is_empty io_vectors)));
]

let suite =
Expand Down

0 comments on commit b6d1f9f

Please sign in to comment.