feature. See also
. The project being documented here (as the example) is the Zig library itself.
Dispatch.SwitchMessage
const SwitchMessage = struct
File
Code
const SwitchMessage = struct {
contexts: Io.fiber.Switch,
pending_task: PendingTask,
const PendingTask = union(enum) {
nothing,
await: *Fiber,
activate: c.dispatch.object_t,
@"resume": c.dispatch.object_t,
group_await: Group,
group_cancel: Group,
mutex_wait: *Mutex.Waiter,
futex_wait: *Futex.Waiter,
futex_wake: *Futex.Waker,
sleep_wait: *SleepWaiter,
after: c.dispatch.time_t,
destroy,
exit,
};
fn handle(message: *const SwitchMessage, ev: *Evented) void {
const thread: *Thread = .current();
thread.current_context = message.contexts.new;
switch (message.pending_task) {
.nothing => {},
.await => |awaiting| {
const awaiter: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.old));
if (@atomicRmw(?*Fiber, &awaiting.link.awaiter, .Xchg, awaiter, .acq_rel) ==
Fiber.finished) ev.queue.async(awaiter, &Fiber.@"resume");
},
.activate => |object| object.activate(),
.@"resume" => |object| object.@"resume"(),
.group_await => |group| {
const fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.old));
if (group.await(ev, fiber)) ev.queue.async(fiber, &Fiber.@"resume");
},
.group_cancel => |group| {
const fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.old));
if (group.cancel(ev, fiber)) ev.queue.async(fiber, &Fiber.@"resume");
},
.mutex_wait => |waiter| {
waiter.sleeper =
.init(ev.queue, @alignCast(@fieldParentPtr("context", message.contexts.old)));
switch (waiter.sleeper.fiber.cancel_protection.check()) {
.unblocked => {},
.blocked => waiter.cancelable = .blocked,
}
waiter.mutex.queue.async(waiter, &Mutex.Waiter.add);
},
.futex_wait => |waiter| {
waiter.sleeper =
.init(ev.queue, @alignCast(@fieldParentPtr("context", message.contexts.old)));
switch (waiter.sleeper.fiber.cancel_protection.check()) {
.unblocked => {},
.blocked => waiter.cancelable = .blocked,
}
waiter.futex.queue.async(waiter, &Futex.Waiter.add);
},
.futex_wake => |waker| {
waker.sleeper =
.init(ev.queue, @alignCast(@fieldParentPtr("context", message.contexts.old)));
waker.futex.queue.async(waker, &Futex.Waker.remove);
},
.sleep_wait => |waiter| {
waiter.sleeper =
.init(ev.queue, @alignCast(@fieldParentPtr("context", message.contexts.old)));
const queue = waiter.cancelable.queue;
switch (waiter.sleeper.fiber.cancel_protection.check()) {
.unblocked => {},
.blocked => waiter.cancelable = .blocked,
}
queue.async(waiter, &SleepWaiter.start);
},
.after => |when| {
const fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.old));
when.after(ev.queue, fiber, &Fiber.@"resume");
},
.destroy => {
const fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.old));
fiber.destroy(ev);
},
.exit => _ = ev.exit_semaphore.signal(),
}
}
}