this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

embed std.io.Writer in PosixTty with 4096-byte buffer

Integrate Zig 0.15.1's new Writer API into the PosixTty structure by
embedding a std.io.Writer field with a 4096-byte buffer. This provides
buffered writing capabilities with proper VTable implementation.

The embedded writer uses @fieldParentPtr to access the parent PosixTty
instance from the drain function, enabling efficient writes to the
terminal file descriptor when the buffer is full or flushed.

Updated write() and opaqueWrite() methods to use the embedded writer
instead of direct posix.write() calls, providing automatic buffering
for better performance by reducing system call overhead.

Amp-Thread-ID: https://ampcode.com/threads/T-e1192d32-b3c3-43a6-b434-33fe5664bf0a
Co-authored-by: Amp <amp@ampcode.com>

+55 -8
+55 -8
src/tty.zig
··· 33 33 /// The file descriptor of the tty 34 34 fd: posix.fd_t, 35 35 36 + /// Write buffer 37 + buffer: [4096]u8, 38 + 39 + /// Embedded writer 40 + writer: std.io.Writer, 41 + 36 42 pub const SignalHandler = struct { 37 43 context: *anyopaque, 38 44 callback: *const fn (context: *anyopaque) void, 39 45 }; 40 46 47 + /// VTable for embedded writer 48 + const vtable = std.io.Writer.VTable{ 49 + .drain = drainVTable, 50 + }; 51 + 52 + fn drainVTable(w: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize { 53 + const self: *PosixTty = @fieldParentPtr("writer", w); 54 + 55 + // First write any buffered data 56 + if (w.end > 0) { 57 + _ = posix.write(self.fd, w.buffer[0..w.end]) catch return error.WriteFailed; 58 + w.end = 0; 59 + } 60 + 61 + // Write each slice in data 62 + var total: usize = 0; 63 + for (data[0..data.len-1]) |slice| { 64 + const n = posix.write(self.fd, slice) catch return error.WriteFailed; 65 + total += n; 66 + } 67 + 68 + // Write the last slice `splat` times 69 + const pattern = data[data.len - 1]; 70 + for (0..splat) |_| { 71 + const n = posix.write(self.fd, pattern) catch return error.WriteFailed; 72 + total += n; 73 + } 74 + 75 + return total; 76 + } 77 + 41 78 /// global signal handlers 42 79 var handlers: [8]SignalHandler = undefined; 43 80 var handler_mutex: std.Thread.Mutex = .{}; ··· 66 103 posix.sigaction(posix.SIG.WINCH, &act, null); 67 104 handler_installed = true; 68 105 69 - const self: PosixTty = .{ 106 + var self: PosixTty = .{ 70 107 .fd = fd, 71 108 .termios = termios, 109 + .buffer = undefined, 110 + .writer = undefined, // Will be set after self is created 111 + }; 112 + 113 + // Initialize the writer to use our embedded buffer 114 + self.writer = .{ 115 + .vtable = &vtable, 116 + .buffer = &self.buffer, 117 + .end = 0, 72 118 }; 73 119 74 120 global_tty = self; ··· 101 147 } 102 148 103 149 /// Write bytes to the tty 104 - pub fn write(self: *const PosixTty, bytes: []const u8) !usize { 105 - return posix.write(self.fd, bytes); 150 + pub fn write(self: *PosixTty, bytes: []const u8) !usize { 151 + return self.writer.write(bytes); 106 152 } 107 153 108 154 pub fn opaqueWrite(ptr: *const anyopaque, bytes: []const u8) !usize { 109 - const self: *const PosixTty = @ptrCast(@alignCast(ptr)); 110 - return posix.write(self.fd, bytes); 155 + const self: *PosixTty = @ptrCast(@alignCast(ptr)); 156 + return self.writer.write(bytes); 111 157 } 112 158 113 - pub fn anyWriter(self: *const PosixTty) std.io.AnyWriter { 159 + pub fn anyWriter(self: *PosixTty) std.io.AnyWriter { 114 160 return .{ 115 161 .context = self, 116 162 .writeFn = PosixTty.opaqueWrite, ··· 204 250 return error.IoctlError; 205 251 } 206 252 207 - pub fn bufferedWriter(self: *const PosixTty) std.io.BufferedWriter(4096, std.io.AnyWriter) { 208 - return std.io.bufferedWriter(self.anyWriter()); 253 + pub fn bufferedWriter(self: *PosixTty) *std.io.Writer { 254 + // The embedded writer is already buffered with a 4096-byte buffer 255 + return &self.writer; 209 256 } 210 257 }; 211 258