feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.park
fn park(
timeout: Io.Timeout,
addr_hint: ?*const anyopaque,
unpark_flag: if (need_unpark_flag) *UnparkFlag else void,
) error
File
Code
fn park(
timeout: Io.Timeout,
addr_hint: ?*const anyopaque,
unpark_flag: if (need_unpark_flag) *UnparkFlag else void,
) error{Timeout}!void {
comptime assert(use_parking_futex or use_parking_sleep);
switch (native_os) {
.windows => {
const raw_timeout = timeoutToWindowsInterval(timeout);
// but it's unclear what that actually does, especially since `NtAlertThreadByThreadId`
// does *not* accept the address so the kernel can't really be using it as a hint. An
// old Microsoft blog post discusses a more traditional futex-like mechanism in the
// kernel which definitely isn't how `RtlWaitOnAddress` works today:
//
// https://devblogs.microsoft.com/oldnewthing/20160826-00/?p=94185
//
// ...so it's possible this argument is simply a remnant which no longer does anything
// (perhaps the implementation changed during development but someone forgot to remove
// this parameter). However, to err on the side of caution, let's match the behavior of
// `RtlWaitOnAddress` and pass the pointer, in case the kernel ever does something
// stupid such as trying to dereference it.
switch (windows.ntdll.NtWaitForAlertByThreadId(
addr_hint,
if (raw_timeout) |*t| t else null,
)) {
.ALERTED => return,
.TIMEOUT => return error.Timeout,
else => unreachable,
}
},
.netbsd => {
var ts_buf: posix.timespec = undefined;
const ts: ?*posix.timespec, const abstime: bool, const clock_real: bool = switch (timeout) {
.none => .{ null, false, false },
.deadline => |timestamp| timeout: {
ts_buf = timestampToPosix(timestamp.raw.nanoseconds);
break :timeout .{ &ts_buf, true, timestamp.clock == .real };
},
.duration => |duration| timeout: {
ts_buf = timestampToPosix(duration.raw.nanoseconds);
break :timeout .{ &ts_buf, false, duration.clock == .real };
},
};
// writes the remaining time into the buffer when the syscall returns.
while (!unpark_flag.swap(false, .acquire)) {
switch (posix.errno(std.c._lwp_park(
if (clock_real) .REALTIME else .MONOTONIC,
.{ .ABSTIME = abstime },
ts,
0,
addr_hint,
null,
))) {
.SUCCESS, .ALREADY, .INTR => {},
.TIMEDOUT => return error.Timeout,
.INVAL => unreachable,
.SRCH => unreachable,
else => unreachable,
}
}
},
.illumos => @panic("TODO: illumos lwp_park"),
else => comptime unreachable,
}
}