authorgravatar for eugenelf10@gmail.comTen Eugene <eugenelf10@gmail.com> 2026-09-21 16:52:49+05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-21 19:29:10+02:00
logbb40a85558625bc4c412fa8c5e67163013772146
tree0d77d0a39a68bbe0b7990f25784edeb886ff6754
parent969db474f3aa273dec52b5e14a934f62b7eda89c

std.Io.Event.waitTimeout: handle spurious wakeups


1 files changed, 14 insertions(+), 8 deletions(-)

lib/std/Io.zig+14-8
......@@ -2052,9 +2052,7 @@ pub const Event = enum(u32) {
20522052
20532053 pub const WaitTimeoutError = error{Timeout} || Cancelable;
20542054
2055 /// Blocks the calling thread until either the logical boolean is set, the timeout expires, or a
2056 /// spurious wakeup occurs. If the timeout expires or a spurious wakeup occurs, `error.Timeout`
2057 /// is returned.
2055 /// Blocks the calling thread until either the logical boolean is set or the timeout expires.
20582056 pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void {
20592057 if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) {
20602058 .unset => unreachable,
......@@ -2068,11 +2066,19 @@ pub const Event = enum(u32) {
20682066 // waiters would wake up when a *new waiter* was added. So it's easiest to just leave
20692067 // the state at `.waiting`---at worst it causes one redundant call to `futexWake`.
20702068 }
2071 try io.futexWaitTimeout(Event, event, .waiting, timeout);
2072 switch (@atomicLoad(Event, event, .acquire)) {
2073 .unset => unreachable, // `reset` called before pending `wait` returned
2074 .waiting => return error.Timeout,
2075 .is_set => return,
2069
2070 const deadline = timeout.toDeadline(io);
2071
2072 while (true) {
2073 try io.futexWaitTimeout(Event, event, .waiting, timeout);
2074 switch (@atomicLoad(Event, event, .acquire)) {
2075 .unset => unreachable, // `reset` called before pending `wait` returned
2076 .waiting => {
2077 const remaining = deadline.toDurationFromNow(io) orelse continue;
2078 if (remaining.raw.nanoseconds <= 0) return error.Timeout;
2079 },
2080 .is_set => return,
2081 }
20762082 }
20772083 }
20782084