std.fs.net.Stream: add writev and writevAll

I noticed that the write function does not properly use non-blocking
I/O. This file needs to be reworked for evented I/O to properly take
advantage of non-blocking writes to network sockets.
This commit is contained in:
Andrew Kelley
2021-02-16 11:01:17 -07:00
parent 9270aae071
commit 68e7726478
2 changed files with 39 additions and 0 deletions

View File

@@ -587,6 +587,7 @@ pub const File = struct {
}
/// See https://github.com/ziglang/zig/issues/7699
/// See equivalent function: `std.net.Stream.writev`.
pub fn writev(self: File, iovecs: []const os.iovec_const) WriteError!usize {
if (is_windows) {
// TODO improve this to use WriteFileScatter
@@ -605,6 +606,7 @@ pub const File = struct {
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial writes from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
/// See equivalent function: `std.net.Stream.writevAll`.
pub fn writevAll(self: File, iovecs: []os.iovec_const) WriteError!void {
if (iovecs.len == 0) return;

View File

@@ -1621,6 +1621,9 @@ pub const Stream = struct {
}
}
/// TODO in evented I/O mode, this implementation incorrectly uses the event loop's
/// file system thread instead of non-blocking. It needs to be reworked to properly
/// use non-blocking I/O.
pub fn write(self: Stream, buffer: []const u8) WriteError!usize {
if (std.Target.current.os.tag == .windows) {
return os.windows.WriteFile(self.handle, buffer, null, io.default_mode);
@@ -1632,6 +1635,40 @@ pub const Stream = struct {
return os.write(self.handle, buffer);
}
}
/// See https://github.com/ziglang/zig/issues/7699
/// See equivalent function: `std.fs.File.writev`.
pub fn writev(self: Stream, iovecs: []const os.iovec_const) WriteError!usize {
if (std.io.is_async) {
// TODO improve to actually take advantage of writev syscall, if available.
if (iovecs.len == 0) return 0;
const first_buffer = iovecs[0].iov_base[0..iovecs[0].iov_len];
try self.write(first_buffer);
return first_buffer.len;
} else {
return os.writev(self.handle, iovecs);
}
}
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial writes from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
/// See equivalent function: `std.fs.File.writevAll`.
pub fn writevAll(self: Stream, iovecs: []os.iovec_const) WriteError!void {
if (iovecs.len == 0) return;
var i: usize = 0;
while (true) {
var amt = try self.writev(iovecs[i..]);
while (amt >= iovecs[i].iov_len) {
amt -= iovecs[i].iov_len;
i += 1;
if (i >= iovecs.len) return;
}
iovecs[i].iov_base += amt;
iovecs[i].iov_len -= amt;
}
}
};
pub const StreamServer = struct {