Skip to content

Commit

Permalink
coro: make it possible to make a task uncanceable
Browse files Browse the repository at this point in the history
  • Loading branch information
Cloudef committed Jul 2, 2024
1 parent 6a20d2f commit d086b45
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/coro.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub const ResetEvent = Sync.ResetEvent;
// Aliases
pub const current = Task.current;
pub const yield = Task.yield;
pub const setCancelable = Task.setCancelable;

/// Nonblocking IO (on a task)
pub const io = struct {
Expand Down
12 changes: 10 additions & 2 deletions src/coro/Frame.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ stack: ?Fiber.Stack = null,
result: *anyopaque,
scheduler: *Scheduler,
canceled: bool = false,
cancelable: bool = true,
status: Status = .active,
yield_state: u8 = 0,
link: List.Node = .{ .data = .{} },
Expand Down Expand Up @@ -158,7 +159,7 @@ pub fn complete(self: *@This(), mode: CompleteMode, comptime Result: type) Resul
var timer: ?std.time.Timer = std.time.Timer.start() catch null;
while (self.status != .completed) {
if (mode == .cancel and tryCancel(self)) break;
if (timer != null and self.status != .io_cancel) {
if (timer != null and self.status != .io_cancel and self.cancelable) {
if (timer.?.read() >= 5 * std.time.ns_per_s) {
log.err("deadlock detected, tearing down the scheduler by a force", .{});
self.scheduler.state = .tear_down;
Expand Down Expand Up @@ -192,8 +193,15 @@ 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) {
if (self.status != .completed and self.cancelable) {
self.canceled = true;
switch (self.status) {
.active => {},
Expand Down
8 changes: 8 additions & 0 deletions src/coro/Task.zig
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ pub inline fn state(self: @This(), T: type) T {

pub const YieldError = error{Canceled};

pub inline fn setCancelable(cancelable: bool) YieldError!void {
if (Frame.current()) |frame| {
try frame.setCancelable(cancelable);
} else {
unreachable;
}
}

pub inline fn yield(yield_state: anytype) YieldError!void {
if (Frame.current()) |frame| {
frame.yield_state = @intFromEnum(yield_state);
Expand Down

0 comments on commit d086b45

Please sign in to comment.