Skip to content

Commit

Permalink
coro: cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
Cloudef committed Jul 3, 2024
1 parent 336945e commit 92e795e
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 38 deletions.
11 changes: 2 additions & 9 deletions src/coro/Frame.zig
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ pub fn deinit(self: *@This()) void {
// stack is now gone, doing anything after this with @This() is ub
}

pub inline fn signal(self: *@This()) void {
pub fn signal(self: *@This()) void {
switch (self.status) {
.active, .io_cancel, .completed => {},
else => |status| self.wakeup(status),
}
}

pub inline fn wakeup(self: *@This(), expected_status: Status) void {
pub fn wakeup(self: *@This(), expected_status: Status) void {
std.debug.assert(self.status == expected_status);
debug("waking up: {}", .{self});
self.status = .active;
Expand Down Expand Up @@ -193,13 +193,6 @@ pub fn complete(self: *@This(), mode: CompleteMode, comptime Result: type) Resul
}
}

pub const SetCancelableError = error{Canceled};

pub inline fn setCancelable(self: *@This(), cancelable: bool) SetCancelableError!void {
if (self.canceled) return error.Canceled;
self.cancelable = cancelable;
}

pub fn tryCancel(self: *@This()) bool {
if (self.status != .completed and self.cancelable) {
self.canceled = true;
Expand Down
6 changes: 4 additions & 2 deletions src/coro/Scheduler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ pub const SpawnOptions = struct {
};

/// Spawns a new task, the task may do local IO operations which will not block the whole process using the `io` namespace functions
/// Call `frame.complete` to collect the result and free the stack
/// Call `task.complete` to collect the result and free the stack
/// Or alternatively `task.cancel` to cancel the task
/// Normally one would use the `spawn` method, but in case a generic functions return type can't be deduced, use this any variant.
pub fn spawnAny(self: *@This(), Result: type, comptime func: anytype, args: anytype, opts: SpawnOptions) SpawnError!Task {
if (self.state == .tear_down) return error.Unexpected;
Expand All @@ -65,7 +66,8 @@ pub fn spawnAny(self: *@This(), Result: type, comptime func: anytype, args: anyt
}

/// Spawns a new task, the task may do local IO operations which will not block the whole process using the `io` namespace functions
/// Call `frame.complete` to collect the result and free the stack
/// Call `task.complete` to collect the result and free the stack
/// Or alternatively `task.cancel` to cancel the task
pub inline fn spawn(self: *@This(), comptime func: anytype, args: anytype, opts: SpawnOptions) SpawnError!Task.Generic(ReturnType(func)) {
var task = try self.spawnAny(ReturnType(func), func, args, opts);
return task.generic(ReturnType(func));
Expand Down
48 changes: 21 additions & 27 deletions src/coro/Task.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ const Frame = @import("Frame.zig");

const Task = @This();

frame: *align(@alignOf(Frame)) anyopaque,
/// Private API for the curious 🏩
frame: *Frame,

fn cast(self: @This()) *Frame {
return @ptrCast(self.frame);
}

pub fn format(self: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
return self.cast().format(fmt, opts, writer);
pub inline fn format(self: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
return self.frame.format(fmt, opts, writer);
}

/// Get the current task, or null if not inside a task
Expand All @@ -25,41 +22,42 @@ pub inline fn current() ?@This() {
}

pub inline fn isComplete(self: @This()) bool {
return self.cast().status == .completed;
return self.frame.status == .completed;
}

pub inline fn signal(self: @This()) void {
self.cast().signal();
self.frame.signal();
}

pub inline fn state(self: @This(), T: type) T {
return @enumFromInt(self.cast().yield_state);
return @enumFromInt(self.frame.yield_state);
}

pub const YieldError = error{Canceled};

pub inline fn setCancelable(cancelable: bool) YieldError!void {
pub fn setCancelable(cancelable: bool) YieldError!void {
if (Frame.current()) |frame| {
try frame.setCancelable(cancelable);
if (frame.canceled) return error.Canceled;
frame.cancelable = cancelable;
} else {
unreachable;
unreachable; // can only be called from a task
}
}

pub inline fn yield(yield_state: anytype) YieldError!void {
pub fn yield(yield_state: anytype) YieldError!void {
if (Frame.current()) |frame| {
frame.yield_state = @intFromEnum(yield_state);
if (frame.yield_state == 0) @panic("yield_state `0` is reserved");
Frame.yield(.yield);
if (frame.canceled) return error.Canceled;
} else {
unreachable;
unreachable; // can only be called from a task
}
}

pub inline fn wakeup(self: @This()) void {
self.cast().yield_state = 0;
self.cast().wakeup(.yield);
self.frame.yield_state = 0;
self.frame.wakeup(.yield);
}

pub inline fn wakeupIf(self: @This(), yield_state: anytype) void {
Expand All @@ -71,33 +69,29 @@ pub inline fn wakeupIf(self: @This(), yield_state: anytype) void {
pub const CompleteMode = Frame.CompleteMode;

pub inline fn complete(self: @This(), mode: CompleteMode, Result: type) Result {
return self.cast().complete(mode, Result);
return self.frame.complete(mode, Result);
}

/// this is same as complete(.cancel, void)
pub inline fn cancel(self: @This()) void {
self.cast().complete(.cancel, void);
self.frame.complete(.cancel, void);
}

pub fn generic(self: @This(), Result: type) Generic(Result) {
pub inline fn generic(self: @This(), Result: type) Generic(Result) {
return .{ .frame = self.frame };
}

pub fn generic2(self: @This(), comptime func: anytype) Generic2(func) {
pub inline fn generic2(self: @This(), comptime func: anytype) Generic2(func) {
return .{ .frame = self.frame };
}

pub fn Generic(comptime ResultType: type) type {
return struct {
pub const Result = ResultType;

frame: *align(@alignOf(Frame)) anyopaque,

fn cast(self: *@This()) *Frame {
return @ptrCast(self.frame);
}
frame: *Frame,

pub fn format(self: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
pub inline fn format(self: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
return self.any().format(fmt, opts, writer);
}

Expand Down

0 comments on commit 92e795e

Please sign in to comment.