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 {...@@ -587,6 +587,7 @@ pub const File = struct {
587 }587 }
588588
589 /// See https://github.com/ziglang/zig/issues/7699589 /// See https://github.com/ziglang/zig/issues/7699
590 /// See equivalent function: `std.net.Stream.writev`.
590 pub fn writev(self: File, iovecs: []const os.iovec_const) WriteError!usize {591 pub fn writev(self: File, iovecs: []const os.iovec_const) WriteError!usize {
591 if (is_windows) {592 if (is_windows) {
592 // TODO improve this to use WriteFileScatter593 // TODO improve this to use WriteFileScatter
...@@ -605,6 +606,7 @@ pub const File = struct {...@@ -605,6 +606,7 @@ pub const File = struct {
605 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in606 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in
606 /// order to handle partial writes from the underlying OS layer.607 /// order to handle partial writes from the underlying OS layer.
607 /// See https://github.com/ziglang/zig/issues/7699608 /// See https://github.com/ziglang/zig/issues/7699
609 /// See equivalent function: `std.net.Stream.writevAll`.
608 pub fn writevAll(self: File, iovecs: []os.iovec_const) WriteError!void {610 pub fn writevAll(self: File, iovecs: []os.iovec_const) WriteError!void {
609 if (iovecs.len == 0) return;611 if (iovecs.len == 0) return;
610612
lib/std/net.zig+37
...@@ -1621,6 +1621,9 @@ pub const Stream = struct {...@@ -1621,6 +1621,9 @@ pub const Stream = struct {
1621 }1621 }
1622 }1622 }
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.
1624 pub fn write(self: Stream, buffer: []const u8) WriteError!usize {1627 pub fn write(self: Stream, buffer: []const u8) WriteError!usize {
1625 if (std.Target.current.os.tag == .windows) {1628 if (std.Target.current.os.tag == .windows) {
1626 return os.windows.WriteFile(self.handle, buffer, null, io.default_mode);1629 return os.windows.WriteFile(self.handle, buffer, null, io.default_mode);
...@@ -1632,6 +1635,40 @@ pub const Stream = struct {...@@ -1632,6 +1635,40 @@ pub const Stream = struct {
1632 return os.write(self.handle, buffer);1635 return os.write(self.handle, buffer);
1633 }1636 }
1634 }1637 }
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 }
1635};1672};
16361673
1637pub const StreamServer = struct {1674pub const StreamServer = struct {