An asynchronous IO runtime
1const Task = @This();
2
3const std = @import("std");
4const io = @import("main.zig");
5
6const Allocator = std.mem.Allocator;
7const Ring = io.Ring;
8
9userdata: ?*anyopaque = null,
10msg: u16 = 0,
11callback: io.Callback = io.noopCallback,
12req: io.Request = .noop,
13
14result: ?io.Result = null,
15
16state: enum {
17 /// The task is free to be scheduled
18 free,
19
20 /// The task is in flight and may not be rescheduled. Some operations generate multiple
21 /// completions, so it is possible to receive a task in Callback and the task is still
22 /// considered to be in flight
23 in_flight,
24
25 /// The task was completed
26 complete,
27
28 /// The operation was canceled
29 canceled,
30} = .free,
31
32/// Deadline for the task to complete, in absolute time. If 0, there is no deadline
33deadline: ?*Task = null,
34
35next: ?*Task = null,
36prev: ?*Task = null,
37
38pub fn setDeadline(
39 self: *Task,
40 rt: *Ring,
41 deadline: io.Timespec,
42) Allocator.Error!void {
43 std.debug.assert(!deadline.isZero());
44 const task = try rt.getTask();
45
46 task.* = .{
47 .callback = io.noopCallback,
48 .userdata = null,
49 .msg = 0,
50 .req = .{ .deadline = deadline },
51 };
52
53 self.deadline = task;
54}
55
56pub fn cancel(
57 self: *Task,
58 rt: *Ring,
59 ctx: io.Context,
60) Allocator.Error!void {
61 const task = try rt.getTask();
62 task.* = .{
63 .callback = ctx.cb,
64 .msg = ctx.msg,
65 .userdata = ctx.ptr,
66 .req = .{ .cancel = .{ .task = self } },
67 };
68 rt.submission_q.push(task);
69}
70
71pub fn userdataCast(self: Task, comptime T: type) *T {
72 return @ptrCast(@alignCast(self.userdata));
73}
74
75pub fn msgToEnum(self: Task, comptime Enum: type) Enum {
76 return @enumFromInt(self.msg);
77}