authorgravatar for eugenelf10@gmail.comTen Eugene <eugenelf10@gmail.com> 2026-09-21 16:52:49+05:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-21 20:13:12+02:00
logc99f5c98c5d69b04444f78666931b93e8f0aab08
tree6ca5e2d64bcfbae68a89a7bd70bf97b52875b777
parentcff70a4050a4ca0ef5ef6be5ee72b425e56ad2d4
signature Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.Io.Event.waitTimeout: handle spurious wakeups


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

lib/std/Io.zig+14-8
...@@ -2021,9 +2021,7 @@ pub const Event = enum(u32) {...@@ -2021,9 +2021,7 @@ pub const Event = enum(u32) {
20212021
2022 pub const WaitTimeoutError = error{Timeout} || Cancelable;2022 pub const WaitTimeoutError = error{Timeout} || Cancelable;
20232023
2024 /// Blocks the calling thread until either the logical boolean is set, the timeout expires, or a2024 /// Blocks the calling thread until either the logical boolean is set or the timeout expires.
2025 /// spurious wakeup occurs. If the timeout expires or a spurious wakeup occurs, `error.Timeout`
2026 /// is returned.
2027 pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void {2025 pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void {
2028 if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) {2026 if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) {
2029 .unset => unreachable,2027 .unset => unreachable,
...@@ -2037,11 +2035,19 @@ pub const Event = enum(u32) {...@@ -2037,11 +2035,19 @@ pub const Event = enum(u32) {
2037 // waiters would wake up when a *new waiter* was added. So it's easiest to just leave2035 // waiters would wake up when a *new waiter* was added. So it's easiest to just leave
2038 // the state at `.waiting`---at worst it causes one redundant call to `futexWake`.2036 // the state at `.waiting`---at worst it causes one redundant call to `futexWake`.
2039 }2037 }
2040 try io.futexWaitTimeout(Event, event, .waiting, timeout);2038
2041 switch (@atomicLoad(Event, event, .acquire)) {2039 const deadline = timeout.toDeadline(io);
2042 .unset => unreachable, // `reset` called before pending `wait` returned2040
2043 .waiting => return error.Timeout,2041 while (true) {
2044 .is_set => return,2042 try io.futexWaitTimeout(Event, event, .waiting, timeout);
2043 switch (@atomicLoad(Event, event, .acquire)) {
2044 .unset => unreachable, // `reset` called before pending `wait` returned
2045 .waiting => {
2046 const remaining = deadline.toDurationFromNow(io) orelse continue;
2047 if (remaining.raw.nanoseconds <= 0) return error.Timeout;
2048 },
2049 .is_set => return,
2050 }
2045 }2051 }
2046 }2052 }
20472053