@@ -8,6 +8,101 @@ const Priority = enum(u8) {
8
8
do_not_run = 3 ,
9
9
};
10
10
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
+
11
106
const TaskStatus = struct {
12
107
reschedule : usize = 0 ,
13
108
scheduled : bool = false ,
0 commit comments