mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 03:44:46 +01:00
std.Io: simplify operate function
- no timeout - no n_wait - infallible
This commit is contained in:
parent
d63172a35d
commit
0deaf9957c
5 changed files with 34 additions and 54 deletions
|
|
@ -148,7 +148,7 @@ pub const VTable = struct {
|
|||
futexWaitUncancelable: *const fn (?*anyopaque, ptr: *const u32, expected: u32) void,
|
||||
futexWake: *const fn (?*anyopaque, ptr: *const u32, max_waiters: u32) void,
|
||||
|
||||
operate: *const fn (?*anyopaque, []Operation, n_wait: usize, Timeout) OperateError!void,
|
||||
operate: *const fn (?*anyopaque, []Operation) void,
|
||||
|
||||
dirCreateDir: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.CreateDirError!void,
|
||||
dirCreateDirPath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.CreateDirPathError!Dir.CreatePathStatus,
|
||||
|
|
@ -257,22 +257,11 @@ pub const Operation = union(enum) {
|
|||
};
|
||||
};
|
||||
|
||||
pub const OperateError = error{ Canceled, Timeout };
|
||||
|
||||
/// Performs all `operations` in a non-deterministic order. Returns after all
|
||||
/// `operations` have been attempted. The degree to which the operations are
|
||||
/// `operations` have been completed. The degree to which the operations are
|
||||
/// performed concurrently is determined by the `Io` implementation.
|
||||
///
|
||||
/// `n_wait` is an amount of operations between `0` and `operations.len` that
|
||||
/// determines how many attempted operations must complete before `operate`
|
||||
/// returns. Operation completion is defined by returning a value other than
|
||||
/// `error.WouldBlock`. If the operation cannot return `error.WouldBlock`, it
|
||||
/// always counts as completing.
|
||||
///
|
||||
/// In the event `error.Canceled` is returned, any number of `operations` may
|
||||
/// still have been completed successfully.
|
||||
pub fn operate(io: Io, operations: []Operation, n_wait: usize, timeout: Timeout) OperateError!void {
|
||||
return io.vtable.operate(io.userdata, operations, n_wait, timeout);
|
||||
pub fn operate(io: Io, operations: []Operation) void {
|
||||
return io.vtable.operate(io.userdata, operations);
|
||||
}
|
||||
|
||||
pub const Limit = enum(usize) {
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ pub fn readStreaming(file: File, io: Io, buffer: []const []u8) Reader.Error!usiz
|
|||
.data = buffer,
|
||||
.result = undefined,
|
||||
} };
|
||||
io.vtable.operate(io.userdata, (&operation)[0..1], 1, .none) catch unreachable;
|
||||
io.vtable.operate(io.userdata, (&operation)[0..1]);
|
||||
return operation.file_read_streaming.result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2268,20 +2268,15 @@ fn futexWake(userdata: ?*anyopaque, ptr: *const u32, max_waiters: u32) void {
|
|||
Thread.futexWake(ptr, max_waiters);
|
||||
}
|
||||
|
||||
fn operate(userdata: ?*anyopaque, operations: []Io.Operation, n_wait: usize, timeout: Io.Timeout) Io.OperateError!void {
|
||||
fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
const t_io = ioBasic(t);
|
||||
_ = t;
|
||||
|
||||
if (is_windows) @panic("TODO");
|
||||
|
||||
const deadline = timeout.toDeadline(t_io) catch |err| switch (err) {
|
||||
error.UnsupportedClock, error.Unexpected => null,
|
||||
};
|
||||
|
||||
var poll_buffer: [100]posix.pollfd = undefined;
|
||||
var map_buffer: [poll_buffer.len]u8 = undefined; // poll_buffer index to operations index
|
||||
var poll_i: usize = 0;
|
||||
var completed: usize = 0;
|
||||
|
||||
// Put all the file reads with nonblocking enabled into the poll set.
|
||||
if (operations.len > poll_buffer.len) @panic("TODO");
|
||||
|
|
@ -2302,7 +2297,6 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation, n_wait: usize, tim
|
|||
poll_i += 1;
|
||||
} else {
|
||||
o.result = fileReadStreaming(o.file, o.data);
|
||||
completed += 1;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -2312,41 +2306,42 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation, n_wait: usize, tim
|
|||
return;
|
||||
}
|
||||
|
||||
const max_poll_ms = std.math.maxInt(i32);
|
||||
|
||||
while (completed < n_wait) {
|
||||
const timeout_ms: i32 = if (deadline) |d| t: {
|
||||
const duration = d.durationFromNow(t_io) catch @panic("TODO make this unreachable");
|
||||
if (duration.raw.nanoseconds <= 0) return error.Timeout;
|
||||
break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds()));
|
||||
} else -1;
|
||||
const syscall = try Syscall.start();
|
||||
const poll_rc = posix.system.poll(&poll_buffer, poll_i, timeout_ms);
|
||||
while (true) {
|
||||
const syscall = Syscall.start() catch |err| switch (err) {
|
||||
error.Canceled => {
|
||||
for (map_buffer[0..poll_i]) |operation_index| {
|
||||
switch (operations[operation_index]) {
|
||||
.noop => unreachable,
|
||||
inline else => |*o| o.result = error.Canceled,
|
||||
}
|
||||
}
|
||||
return;
|
||||
},
|
||||
};
|
||||
const poll_rc = posix.system.poll(&poll_buffer, poll_i, -1);
|
||||
syscall.finish();
|
||||
switch (posix.errno(poll_rc)) {
|
||||
.SUCCESS => {
|
||||
if (poll_rc == 0) {
|
||||
// Although spurious timeouts are OK, when no deadline
|
||||
// is passed we must not return `error.Timeout`.
|
||||
if (deadline == null) continue;
|
||||
return error.Timeout;
|
||||
}
|
||||
for (poll_buffer[0..poll_i], map_buffer[0..poll_i]) |*poll_fd, operation_index| {
|
||||
if (poll_fd.revents == 0) continue;
|
||||
poll_fd.fd = -1; // Disarm this operation.
|
||||
switch (operations[operation_index]) {
|
||||
.noop => unreachable,
|
||||
.file_read_streaming => |*o| {
|
||||
o.result = fileReadStreaming(o.file, o.data);
|
||||
completed += 1;
|
||||
},
|
||||
}
|
||||
// Spurious timeout; handle same as INTR.
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
},
|
||||
.INTR => continue,
|
||||
else => @panic("TODO handle unexpected error from poll()"),
|
||||
}
|
||||
}
|
||||
|
||||
for (poll_buffer[0..poll_i], map_buffer[0..poll_i]) |*poll_fd, operation_index| {
|
||||
if (poll_fd.revents == 0) continue;
|
||||
switch (operations[operation_index]) {
|
||||
.noop => unreachable,
|
||||
.file_read_streaming => |*o| {
|
||||
o.result = fileReadStreaming(o.file, o.data);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dirCreateDir = switch (native_os) {
|
||||
|
|
|
|||
|
|
@ -502,7 +502,6 @@ pub const RunOptions = struct {
|
|||
create_no_window: bool = true,
|
||||
/// Darwin-only. Disable ASLR for the child process.
|
||||
disable_aslr: bool = false,
|
||||
timeout: Io.Timeout = .none,
|
||||
};
|
||||
|
||||
pub const RunResult = struct {
|
||||
|
|
@ -544,7 +543,6 @@ pub fn run(gpa: Allocator, io: Io, options: RunOptions) RunError!RunResult {
|
|||
.stderr = &stderr,
|
||||
.stdout_limit = options.stdout_limit,
|
||||
.stderr_limit = options.stderr_limit,
|
||||
.timeout = options.timeout,
|
||||
});
|
||||
|
||||
return .{
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ pub const CollectOutputOptions = struct {
|
|||
allocator: ?Allocator = null,
|
||||
stdout_limit: Io.Limit = .unlimited,
|
||||
stderr_limit: Io.Limit = .unlimited,
|
||||
timeout: Io.Timeout = .none,
|
||||
};
|
||||
|
||||
/// Collect the output from the process's stdout and stderr. Will return once
|
||||
|
|
@ -174,7 +173,7 @@ pub fn collectOutput(child: *const Child, io: Io, options: CollectOutputOptions)
|
|||
var all_done = true;
|
||||
var any_canceled = false;
|
||||
var other_err: (error{StreamTooLong} || Io.File.Reader.Error)!void = {};
|
||||
const op_result = io.vtable.operate(io.userdata, &reads, 1, options.timeout);
|
||||
io.vtable.operate(io.userdata, &reads);
|
||||
for (&reads, &lists, &limits, &dones) |*read, list, limit, *done| {
|
||||
if (done.*) continue;
|
||||
const n = read.file_read_streaming.result catch |err| switch (err) {
|
||||
|
|
@ -197,7 +196,6 @@ pub fn collectOutput(child: *const Child, io: Io, options: CollectOutputOptions)
|
|||
if (list.items.len > @intFromEnum(limit)) other_err = error.StreamTooLong;
|
||||
}
|
||||
if (any_canceled) return error.Canceled;
|
||||
try op_result; // could be error.Canceled
|
||||
try other_err;
|
||||
if (all_done) return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue