async: enforce synchronous logging by routing async.zig logs through std.log.defaultLog to avoid panics when using async.LogFn

This commit is contained in:
Tarry Singh 2024-09-17 09:03:48 +00:00
parent aec7072837
commit fa4a8d8de4
2 changed files with 23 additions and 18 deletions

View File

@ -10,13 +10,14 @@
//! * Done: set in runcoro //! * Done: set in runcoro
//! * id.invocation: incremented in ThreadState.switchTo //! * id.invocation: incremented in ThreadState.switchTo
const std = @import("std"); const std = @import("std");
const stdx = @import("stdx");
const builtin = @import("builtin"); const builtin = @import("builtin");
const base = @import("coro_base.zig");
const stack = @import("stack.zig");
const Executor = @import("executor.zig").Executor;
const log = std.log.scoped(.@"zml/async"); const stdx = @import("stdx");
const base = @import("coro_base.zig");
const Executor = @import("executor.zig").Executor;
const stack = @import("stack.zig");
pub const StackT = stack.Stack;
// Public API // Public API
// ============================================================================ // ============================================================================
@ -25,8 +26,6 @@ pub const Error = error{
StackOverflow, StackOverflow,
SuspendFromMain, SuspendFromMain,
}; };
pub const StackT = stack.Stack;
pub const Frame = *Coro; pub const Frame = *Coro;
/// Await the coroutine(s). /// Await the coroutine(s).
@ -76,7 +75,7 @@ pub fn xresume(frame: anytype) void {
/// Must be called from within a coroutine (i.e. not the top level). /// Must be called from within a coroutine (i.e. not the top level).
pub fn xsuspend() void { pub fn xsuspend() void {
xsuspendSafe() catch |e| { xsuspendSafe() catch |e| {
log.err("{any}", .{e}); log(.err, "{any}", .{e});
@panic("xsuspend"); @panic("xsuspend");
}; };
} }
@ -160,10 +159,9 @@ const Coro = struct {
fn runcoro(from: *base.Coro, this: *base.Coro) callconv(.C) noreturn { fn runcoro(from: *base.Coro, this: *base.Coro) callconv(.C) noreturn {
const from_coro: *Coro = @fieldParentPtr("impl", from); const from_coro: *Coro = @fieldParentPtr("impl", from);
const this_coro: *Coro = @fieldParentPtr("impl", this); const this_coro: *Coro = @fieldParentPtr("impl", this);
log.debug("coro start {any}", .{this_coro.id}); log(.debug, "coro start {any}", .{this_coro.id});
@call(.auto, this_coro.func, .{}); @call(.auto, this_coro.func, .{});
this_coro.status = .Done; this_coro.status = .Done;
log.debug("coro done {any}", .{this_coro.id});
thread_state.switchOut(from_coro); thread_state.switchOut(from_coro);
// Never returns // Never returns
@ -317,7 +315,7 @@ const ThreadState = struct {
/// Called from resume /// Called from resume
fn switchIn(self: *ThreadState, target: Frame) void { fn switchIn(self: *ThreadState, target: Frame) void {
log.debug("coro resume {any} from {any}", .{ target.id, self.current().id }); log(.debug, "coro resume {any} from {any}", .{ target.id, self.current().id });
// Switch to target, setting this coro as the resumer. // Switch to target, setting this coro as the resumer.
self.switchTo(target, true); self.switchTo(target, true);
@ -332,7 +330,7 @@ const ThreadState = struct {
/// Called from suspend /// Called from suspend
fn switchOut(self: *ThreadState, target: Frame) void { fn switchOut(self: *ThreadState, target: Frame) void {
log.debug("coro suspend {any} to {any}", .{ self.current().id, target.id }); log(.debug, "coro suspend {any} to {any}", .{ self.current().id, target.id });
self.switchTo(target, false); self.switchTo(target, false);
} }
@ -553,3 +551,10 @@ test "resume self" {
xresume(xframe()); xresume(xframe());
try std.testing.expectEqual(1, 1); try std.testing.expectEqual(1, 1);
} }
pub fn log(comptime level: std.log.Level, comptime fmt: []const u8, args: anytype) void {
if (comptime !std.log.logEnabled(level, .@"zml/async")) return;
// Since this logs are to debug the async runtime, we want it to happen synchronously.
std.log.defaultLog(level, .@"zml/async", fmt, args);
}

View File

@ -1,9 +1,9 @@
const std = @import("std"); const std = @import("std");
const stdx = @import("stdx");
const libcoro = @import("coro.zig");
const libcoro_options = @import("libcoro_options");
const log = std.log.scoped(.@"zml/async"); const libcoro_options = @import("libcoro_options");
const stdx = @import("stdx");
const libcoro = @import("coro.zig");
pub const Executor = struct { pub const Executor = struct {
const Self = @This(); const Self = @This();
@ -43,14 +43,14 @@ pub const Executor = struct {
var now = self.readyq; var now = self.readyq;
self.readyq = .{}; self.readyq = .{};
log.debug("Executor.tick readyq_len={d}", .{now.len()}); libcoro.log(.debug, "Executor.tick readyq.len={d}", .{now.len()});
var count: usize = 0; var count: usize = 0;
while (now.pop()) |func| : (count += 1) { while (now.pop()) |func| : (count += 1) {
func.run(); func.run();
} }
log.debug("Executor.tick done", .{}); libcoro.log(.debug, "Executor.tick done", .{});
return count > 0; return count > 0;
} }