Hacker News
points by imtringued 23 hours ago | 0 comments
This is AI generated so it could be wrong:

    const std = @import("std");
    
    fn performTasks(io: std.Io) !void {
        var group: std.Io.Group = .init;
        errdefer group.cancel(io);

        // Launch concurrent background jobs
        try group.async(io, simulateWorker, .{ io, 1 });
        try group.async(io, simulateWorker, .{ io, 2 });

        // Wait for all group tasks to complete
        try group.await(io);
    }
    
    fn simulateWorker(io: std.Io, id: usize) void {
        std.log.info("Worker {d} started...", .{id});
        
        // Any blocking operation (like sleeping) routes through 'io'
        // Under the hood, this will either block an OS thread or yield an event loop stack.
        io.sleep(.fromSeconds(1), .awake) catch {};
        
        std.log.info("Worker {d} finished!", .{id});
    }
    
    pub fn main() !void {
        var gpa_alloc = std.heap.GeneralPurposeAllocator(.{}){};
        defer _ = gpa_alloc.deinit();
        const allocator = gpa_alloc.allocator();
    
        // Initialize the Threaded I/O backend
        var threaded = std.Io.Threaded.init(allocator, .{
            .async_limit = std.Io.Limit.limited(4), // Max concurrent tasks in the pool
        });
        defer threaded.deinit();
        
        // Extract the generic I/O interface pointer
        const io = threaded.io();

        std.log.info("Running on Threaded backend:", .{});
        try performTasks(io);
    }


    pub fn main() !void {
        var gpa_alloc = std.heap.GeneralPurposeAllocator(.{}){};
        defer _ = gpa_alloc.deinit();
        const allocator = gpa_alloc.allocator();

        // Initialize the Evented (non-blocking) backend
        var evented: std.Io.Evented = undefined;
        try evented.init(allocator, .{
            .thread_limit = 4, // Worker threads running the event loop
        });
        defer evented.deinit();
    
        // Extract the exact same generic interface
        const io = evented.io();

        std.log.info("Running on Evented backend:", .{});
        try performTasks(io);
    }


std.Io.Threaded and std.Io.Evented are two types of IO backends. std.Io.Threaded uses blocking IO primitives and Evented uses asynchronous IO primitives. Switching between backends is done via dynamic dispatch, the used backend is passed in via an explicit function parameter.

The only real question you should have is, how does the "non-blocking" case work when the interface is still a synchronous call? Well, the answer is quite boring... You just call into the scheduler and it runs the other task inside the blocked operation.

I was promised hidden magic and implicit logic! Now I want a refund!

Aún no hay comentarios.