authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-16 11:01:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-16 11:01:17-07:00
log68e7726478f89ca27127e68b79112c12ac7415f7
treeac0cdc8ecf8566513c3d1685221376e87ce2e612
parent9270aae071a4ee840193afe1162b24945cbd6d9e

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.

2 files changed, 39 insertions(+), 0 deletions(-)

lib/std/fs/file.zig+2
......@@ -587,6 +587,7 @@ pub const File = struct {
587587 }
588588
589589 /// See https://github.com/ziglang/zig/issues/7699
590 /// See equivalent function: `std.net.Stream.writev`.
590591 pub fn writev(self: File, iovecs: []const os.iovec_const) WriteError!usize {
591592 if (is_windows) {
592593 // TODO improve this to use WriteFileScatter
......@@ -605,6 +606,7 @@ pub const File = struct {
605606 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in
606607 /// order to handle partial writes from the underlying OS layer.
607608 /// See https://github.com/ziglang/zig/issues/7699
609 /// See equivalent function: `std.net.Stream.writevAll`.
608610 pub fn writevAll(self: File, iovecs: []os.iovec_const) WriteError!void {
609611 if (iovecs.len == 0) return;
610612
lib/std/net.zig+37
......@@ -1621,6 +1621,9 @@ pub const Stream = struct {
16211621 }
16221622 }
16231623
1624 /// TODO in evented I/O mode, this implementation incorrectly uses the event loop's
1625 /// file system thread instead of non-blocking. It needs to be reworked to properly
1626 /// use non-blocking I/O.
16241627 pub fn write(self: Stream, buffer: []const u8) WriteError!usize {
16251628 if (std.Target.current.os.tag == .windows) {
16261629 return os.windows.WriteFile(self.handle, buffer, null, io.default_mode);
......@@ -1632,6 +1635,40 @@ pub const Stream = struct {
16321635 return os.write(self.handle, buffer);
16331636 }
16341637 }
1638
1639 /// See https://github.com/ziglang/zig/issues/7699
1640 /// See equivalent function: `std.fs.File.writev`.
1641 pub fn writev(self: Stream, iovecs: []const os.iovec_const) WriteError!usize {
1642 if (std.io.is_async) {
1643 // TODO improve to actually take advantage of writev syscall, if available.
1644 if (iovecs.len == 0) return 0;
1645 const first_buffer = iovecs[0].iov_base[0..iovecs[0].iov_len];
1646 try self.write(first_buffer);
1647 return first_buffer.len;
1648 } else {
1649 return os.writev(self.handle, iovecs);
1650 }
1651 }
1652
1653 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in
1654 /// order to handle partial writes from the underlying OS layer.
1655 /// See https://github.com/ziglang/zig/issues/7699
1656 /// See equivalent function: `std.fs.File.writevAll`.
1657 pub fn writevAll(self: Stream, iovecs: []os.iovec_const) WriteError!void {
1658 if (iovecs.len == 0) return;
1659
1660 var i: usize = 0;
1661 while (true) {
1662 var amt = try self.writev(iovecs[i..]);
1663 while (amt >= iovecs[i].iov_len) {
1664 amt -= iovecs[i].iov_len;
1665 i += 1;
1666 if (i >= iovecs.len) return;
1667 }
1668 iovecs[i].iov_base += amt;
1669 iovecs[i].iov_len -= amt;
1670 }
1671 }
16351672};
16361673
16371674pub const StreamServer = struct {