feature. See also
. The project being documented here (as the example) is the Zig library itself.
Dispatch.Cancelable
const Cancelable = struct
File
Code
const Cancelable = struct {
required_align: void align(2) = {},
queue: c.dispatch.queue_t,
cancel: c.dispatch.function_t,
const fn_ptr_align = std.meta.alignment(c.dispatch.function_t);
const is_blocked: c.dispatch.function_t = @ptrFromInt(fn_ptr_align * 1);
const is_requested: c.dispatch.function_t = @ptrFromInt(fn_ptr_align * 2);
const blocked: Cancelable = .{ .queue = undefined, .cancel = is_blocked };
const RequestedError = error{CancelRequested};
fn enter(cancelable: *Cancelable, fiber: *Fiber) RequestedError!void {
const function = cancelable.cancel;
assert(function != is_requested);
if (function == is_blocked) {
@branchHint(.unlikely);
return;
}
if (@cmpxchgStrong(
Fiber.CancelStatus,
&fiber.cancel_status,
.{ .requested = false, .awaiting = .nothing },
.{ .requested = false, .awaiting = .fromCancelable(cancelable) },
.release,
.monotonic,
)) |cancel_status| {
assert(cancel_status.requested and cancel_status.awaiting == .nothing);
cancelable.cancel = is_requested;
return error.CancelRequested;
}
}
fn leave(cancelable: *Cancelable, fiber: *Fiber) RequestedError!void {
const function = cancelable.cancel;
assert(function != is_requested);
if (function == is_blocked) {
@branchHint(.unlikely);
return;
}
const cancel_status = @atomicRmw(Fiber.CancelStatus, &fiber.cancel_status, .And, .{
.requested = true,
.awaiting = .nothing,
}, .monotonic);
assert(cancel_status.awaiting.toCancelable() == cancelable);
if (cancel_status.requested) return error.CancelRequested;
}
fn async(cancelable: *Cancelable) void {
const function = cancelable.cancel;
assert(function != is_blocked and function != is_requested);
cancelable.queue.async(cancelable, function);
}
fn requested(cancelable: *Cancelable, fiber: *Fiber) void {
const function = cancelable.cancel;
assert(function != is_blocked and function != is_requested);
assert(@atomicLoad(Fiber.CancelStatus, &fiber.cancel_status, .monotonic) == Fiber.CancelStatus{
.requested = true,
.awaiting = .fromCancelable(cancelable),
});
cancelable.cancel = is_requested;
@atomicStore(Fiber.CancelStatus, &fiber.cancel_status, .{
.requested = true,
.awaiting = .nothing,
}, .monotonic);
}
fn acknowledge(cancelable: *Cancelable, fiber: *Fiber) Io.Cancelable!void {
if (cancelable.cancel == is_requested) {
@branchHint(.unlikely);
fiber.cancel_protection.acknowledge();
return error.Canceled;
}
}
}