feature. See also
. The project being documented here (as the example) is the Zig library itself.
Kqueue.SwitchMessage
const SwitchMessage = struct
File
Code
const SwitchMessage = struct {
contexts: Io.fiber.Switch,
pending_task: PendingTask,
const PendingTask = union(enum) {
nothing,
reschedule,
recycle: *Fiber,
register_awaiter: *?*Fiber,
exit,
};
fn handle(message: *const SwitchMessage, k: *Kqueue) void {
const thread: *Thread = .current();
thread.current_context = message.contexts.new;
switch (message.pending_task) {
.nothing => {},
.reschedule => if (message.contexts.old != &thread.idle_context) {
const prev_fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.old));
assert(prev_fiber.queue_next == null);
k.schedule(thread, .{ .head = prev_fiber, .tail = prev_fiber });
},
.recycle => |fiber| {
k.recycle(fiber);
},
.register_awaiter => |awaiter| {
const prev_fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.old));
assert(prev_fiber.queue_next == null);
if (@atomicRmw(?*Fiber, awaiter, .Xchg, prev_fiber, .acq_rel) == Fiber.finished)
k.schedule(thread, .{ .head = prev_fiber, .tail = prev_fiber });
},
.exit => for (k.threads.allocated[0..@atomicLoad(u32, &k.threads.active, .acquire)]) |*each_thread| {
const changes = [_]posix.Kevent{
.{
.ident = 0,
.filter = std.c.EVFILT.USER,
.flags = std.c.EV.ADD | std.c.EV.ONESHOT,
.fflags = std.c.NOTE.TRIGGER,
.data = 0,
.udata = @backingInt(Completion.UserData.exit),
},
};
_ = kevent(each_thread.kq_fd, &changes, &.{}, null) catch |err| {
@panic(@errorName(err));
};
},
}
}
}