Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

idle

Kqueue.idle
fn idle(k: *Kqueue, thread: *Thread) void

File

lib/std/Io/Kqueue.zig:429

Code

fn idle(k: *Kqueue, thread: *Thread) void {
    var events_buffer: [changes_buffer_len]posix.Kevent = undefined;
    var maybe_ready_fiber: ?*Fiber = null;
    while (true) {
        while (maybe_ready_fiber orelse k.findReadyFiber(thread)) |ready_fiber| {
            k.yield(ready_fiber, .nothing);
            maybe_ready_fiber = null;
        }
        const n = kevent(thread.kq_fd, &.{}, &events_buffer, null) catch |err| {
            // TODO handle EINTR for cancellation purposes
            @panic(@errorName(err)); // TODO
        };
        var maybe_ready_queue: ?Fiber.Queue = null;
        for (events_buffer[0..n]) |event| switch (@as(Completion.UserData, @fromBackingInt(@intCast(event.udata)))) {
            .unused => unreachable, // bad submission queued?
            .wakeup => {},
            .cleanup => @panic("failed to notify other threads that we are exiting"),
            .exit => {
                assert(maybe_ready_fiber == null and maybe_ready_queue == null); // pending async
                return;
            },
            _ => {
                const event_head_fiber: *Fiber = @ptrFromInt(event.udata);
                const event_tail_fiber = thread.wait_queues.fetchSwapRemove(.{
                    .ident = event.ident,
                    .filter = event.filter,
                }).?.value;
                assert(event_tail_fiber.queue_next == null);

                // TODO reevaluate this logic
                event_head_fiber.resultPointer(Completion).* = .{
                    .flags = event.flags,
                    .fflags = event.fflags,
                    .data = event.data,
                };

                queue_ready: {
                    const head: *Fiber = if (maybe_ready_fiber == null) f: {
                        maybe_ready_fiber = event_head_fiber;
                        const next = event_head_fiber.queue_next orelse break :queue_ready;
                        event_head_fiber.queue_next = null;
                        break :f next;
                    } else event_head_fiber;

                    if (maybe_ready_queue) |*ready_queue| {
                        ready_queue.tail.queue_next = head;
                        ready_queue.tail = event_tail_fiber;
                    } else {
                        maybe_ready_queue = .{ .head = head, .tail = event_tail_fiber };
                    }
                }
            },
        };
        if (maybe_ready_queue) |ready_queue| k.schedule(thread, ready_queue);
    }
}