Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using completion in multi-threaded application #134

Open
fnzr opened this issue Jan 16, 2025 · 0 comments
Open

Using completion in multi-threaded application #134

fnzr opened this issue Jan 16, 2025 · 0 comments

Comments

@fnzr
Copy link

fnzr commented Jan 16, 2025

This is a general question, I probably just don't understand things enough.

The following program prints "timer" to the console every second, and when something gets written to the stdin, the program print "received stdin", sleeps 5 seconds then prints "end stdin".

const std = @import("std");
const xev = @import("xev");

pub fn main() !void {
    var tpool = xev.ThreadPool.init(.{});
    defer tpool.deinit();
    defer tpool.shutdown();

    var loop = try xev.Loop.init(.{ .thread_pool = &tpool });
    defer loop.deinit();

    var stdin_completion = .{
        .op = .{
            .poll = .{
                .fd = std.io.getStdIn().handle,
                .events = 1,
            },
        },
        .userdata = null,
        .callback = (struct {
            fn callback(_: ?*anyopaque, _: *xev.Loop, _: *xev.Completion, _: xev.Result) xev.CallbackAction {
                std.io.getStdOut().writer().writeAll("received stdin\n") catch unreachable;
                _ = std.io.getStdIn().reader().skipUntilDelimiterOrEof('\n') catch unreachable;
                std.time.sleep(std.time.ns_per_s * 5);
                std.io.getStdOut().writer().writeAll("end stdin\n") catch unreachable;
                return .rearm;
            }
        }).callback,
    };
    loop.add(&stdin_completion);

    var watcher = try xev.Timer.init();
    defer watcher.deinit();
    var timer_completion: xev.Completion = undefined;
    watcher.run(&loop, &timer_completion, 1000, xev.Timer, &watcher, &timerCallback);

    try loop.run(.until_done);
}
fn timerCallback(
    watcher: ?*xev.Timer,
    loop: *xev.Loop,
    c: *xev.Completion,
    result: xev.Timer.RunError!void,
) xev.CallbackAction {
    _ = result catch unreachable;
    std.io.getStdOut().writer().writeAll("timer\n") catch unreachable;
    watcher.?.reset(loop, c, c, 1000, xev.Timer, watcher.?, &timerCallback);
    return .disarm;
}

The issue is, when the stdin event is triggered, the timer is stopped until the stdin callback exits.

I can solve this problem by using the ThreadPool and inside the Task, handle the stdin, but then I lose access to the xev.Completion and on-demand callback (I'd need a while(true) to read stdin)

Is there a way to run both the timer and stdin callbacks concurrently?

extra question: what are these poll events? To be honest I kinda guessed 1 and it worked as I wanted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant