feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.parking_sleep
const parking_sleep = struct
File
Code
const parking_sleep = struct {
comptime {
assert(use_parking_sleep);
}
fn sleep(timeout: Io.Timeout) Io.Cancelable!void {
const opt_thread = Thread.current;
cancelable: {
const thread = opt_thread orelse break :cancelable;
switch (thread.cancel_protection) {
.blocked => break :cancelable,
.unblocked => {},
}
thread.futex_waiter = null;
{
const old_status = thread.status.fetchOr(
.{ .cancelation = @fromBackingInt(@intCast(0b001)), .awaitable = .null },
.release,
);
switch (old_status.cancelation) {
.none => {},
.canceling => return error.Canceled,
.canceled => break :cancelable,
.parked => unreachable,
.blocked => unreachable,
.blocked_alertable => unreachable,
.blocked_alertable_canceling => unreachable,
.blocked_canceling => unreachable,
}
}
if (park(timeout, null, if (need_unpark_flag) &thread.unpark_flag)) {
const old_status = thread.status.load(.monotonic);
assert(old_status.cancelation == .canceling);
thread.status.store(
.{ .cancelation = .canceled, .awaitable = old_status.awaitable },
.monotonic,
);
return error.Canceled;
} else |err| switch (err) {
error.Timeout => {
const old_status = thread.status.fetchAnd(
.{ .cancelation = @fromBackingInt(@intCast(0b110)), .awaitable = .all_ones },
.monotonic,
);
switch (old_status.cancelation) {
.parked => return,
.canceling => {
// us for a cancelation. Whoever did that will have called `unpark`, so
// drop that unpark request by waiting for it.
// Status is still `.canceling`.
park(.none, null, if (need_unpark_flag) &thread.unpark_flag) catch |e| switch (e) {
error.Timeout => unreachable,
};
return;
},
.none => unreachable,
.canceled => unreachable,
.blocked => unreachable,
.blocked_alertable => unreachable,
.blocked_canceling => unreachable,
.blocked_alertable_canceling => unreachable,
}
},
}
}
var dummy_flag: UnparkFlag = unpark_flag_init;
if (park(timeout, null, if (need_unpark_flag) &dummy_flag)) {
unreachable;
} else |err| switch (err) {
error.Timeout => return,
}
}
}