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) {...@@ -2052,9 +2052,7 @@ pub const Event = enum(u32) {
20522052
2053 pub const WaitTimeoutError = error{Timeout} || Cancelable;2053 pub const WaitTimeoutError = error{Timeout} || Cancelable;
20542054
2055 /// Blocks the calling thread until either the logical boolean is set, the timeout expires, or a2055 /// Blocks the calling thread until either the logical boolean is set or the timeout expires.
2056 /// spurious wakeup occurs. If the timeout expires or a spurious wakeup occurs, `error.Timeout`
2057 /// is returned.
2058 pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void {2056 pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void {
2059 if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) {2057 if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) {
2060 .unset => unreachable,2058 .unset => unreachable,
...@@ -2068,11 +2066,19 @@ pub const Event = enum(u32) {...@@ -2068,11 +2066,19 @@ pub const Event = enum(u32) {
2068 // waiters would wake up when a *new waiter* was added. So it's easiest to just leave2066 // waiters would wake up when a *new waiter* was added. So it's easiest to just leave
2069 // the state at `.waiting`---at worst it causes one redundant call to `futexWake`.2067 // the state at `.waiting`---at worst it causes one redundant call to `futexWake`.
2070 }2068 }
2071 try io.futexWaitTimeout(Event, event, .waiting, timeout);2069
2072 switch (@atomicLoad(Event, event, .acquire)) {2070 const deadline = timeout.toDeadline(io);
2073 .unset => unreachable, // `reset` called before pending `wait` returned2071
2074 .waiting => return error.Timeout,2072 while (true) {
2075 .is_set => return,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 }
2076 }2082 }
2077 }2083 }
20782084