| ... | ... | @@ -2052,9 +2052,7 @@ pub const Event = enum(u32) { |
| 2052 | 2052 | |
| 2053 | 2053 | pub const WaitTimeoutError = error{Timeout} || Cancelable; |
| 2054 | 2054 | |
| 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. |
| 2058 | 2056 | pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void { |
| 2059 | 2057 | if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) { |
| 2060 | 2058 | .unset => unreachable, |
| ... | ... | @@ -2068,11 +2066,19 @@ pub const Event = enum(u32) { |
| 2068 | 2066 | // waiters would wake up when a *new waiter* was added. So it's easiest to just leave |
| 2069 | 2067 | // the state at `.waiting`---at worst it causes one redundant call to `futexWake`. |
| 2070 | 2068 | } |
| 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 | } |
| 2076 | 2082 | } |
| 2077 | 2083 | } |
| 2078 | 2084 | |