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