Skip to content

Commit b9b7b93

Browse files
committed
Add Future
1 parent 3221552 commit b9b7b93

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

src/utils/Scheduler.zig

+95
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,101 @@ const Priority = enum(u8) {
88
do_not_run = 3,
99
};
1010

11+
pub fn Future(comptime T: type) type {
12+
const Started = enum(u8) {
13+
not_started,
14+
started,
15+
cancelled,
16+
};
17+
18+
return struct {
19+
result: ?T = null,
20+
cancelled: std.atomic.Value(bool),
21+
started: std.atomic.Value(Started),
22+
finished: std.Thread.ResetEvent,
23+
24+
pub fn init() @This() {
25+
return .{
26+
.cancelled = std.atomic.Value(bool).init(false),
27+
.started = std.atomic.Value(Started).init(.not_started),
28+
.finished = .{},
29+
};
30+
}
31+
32+
pub fn cancel(self: *@This()) void {
33+
self.markAsCancelled() catch return;
34+
self.markAsStarted(.cancelled) catch return;
35+
self.markAsFinished(null);
36+
}
37+
38+
pub fn isCancelled(self: @This()) bool {
39+
return self.cancelled.load(.acquire);
40+
}
41+
42+
pub fn isStarted(self: @This()) bool {
43+
return self.started.load(.acquire) == .started;
44+
}
45+
46+
pub fn isRunning(self: @This()) bool {
47+
return self.isStarted() and !self.isFinished();
48+
}
49+
50+
pub fn isFinished(self: @This()) bool {
51+
return self.finished.isSet();
52+
}
53+
54+
pub fn waitForFinished(self: *@This()) void {
55+
self.finished.wait();
56+
}
57+
58+
pub fn getResult(self: @This()) ?T {
59+
if (self.isFinished()) {
60+
return self.result;
61+
}
62+
return null;
63+
}
64+
65+
fn markAsCancelled(self: *@This()) !void {
66+
const res = self.cancelled.cmpxchgStrong(false, true, .seq_cst, .seq_cst);
67+
if (res != null) {
68+
return error.AlreadyCancelled;
69+
}
70+
}
71+
72+
fn markAsStarted(self: *@This(), status: Started) !void {
73+
std.debug.assert(status != .not_started);
74+
const res = self.started.cmpxchgStrong(.not_started, status, .seq_cst, .seq_cst);
75+
if (res != null) {
76+
return error.AlreadyStarted;
77+
}
78+
}
79+
80+
fn markAsFinished(self: *@This(), result: ?T) void {
81+
std.debug.assert(!self.finished.isSet());
82+
self.result = result;
83+
self.finished.set();
84+
}
85+
};
86+
}
87+
88+
test "Future" {
89+
var fut = Future(u8).init();
90+
try std.testing.expectEqual(false, fut.isStarted());
91+
try std.testing.expectEqual(false, fut.isRunning());
92+
try std.testing.expectEqual(false, fut.isFinished());
93+
try std.testing.expectEqual(false, fut.isCancelled());
94+
try std.testing.expectEqual(null, fut.getResult());
95+
96+
fut.cancel();
97+
fut.waitForFinished();
98+
99+
try std.testing.expectEqual(false, fut.isStarted());
100+
try std.testing.expectEqual(false, fut.isRunning());
101+
try std.testing.expectEqual(true, fut.isFinished());
102+
try std.testing.expectEqual(true, fut.isCancelled());
103+
try std.testing.expectEqual(null, fut.getResult());
104+
}
105+
11106
const TaskStatus = struct {
12107
reschedule: usize = 0,
13108
scheduled: bool = false,

0 commit comments

Comments
 (0)