@@ -49,6 +49,11 @@ pub const SingleThreaded = struct {
49
49
// This is a weak way to cancel all future Zig callbacks.
50
50
zig_ctx_id : u32 = 0 ,
51
51
52
+ // The MacOS event loop doesn't support cancellation. We use this to track
53
+ // cancellation ids and, on the timeout callback, we can can check here
54
+ // to see if it's been cancelled.
55
+ cancelled : std .AutoHashMapUnmanaged (usize , void ),
56
+
52
57
cancel_pool : MemoryPool (ContextCancel ),
53
58
timeout_pool : MemoryPool (ContextTimeout ),
54
59
event_callback_pool : MemoryPool (EventCallbackContext ),
@@ -63,6 +68,7 @@ pub const SingleThreaded = struct {
63
68
pub fn init (alloc : std.mem.Allocator ) ! Self {
64
69
return Self {
65
70
.alloc = alloc ,
71
+ .cancelled = .{},
66
72
.io = try IO .init (32 , 0 ),
67
73
.js_events_nb = 0 ,
68
74
.zig_events_nb = 0 ,
@@ -81,11 +87,14 @@ pub const SingleThreaded = struct {
81
87
break ;
82
88
};
83
89
}
84
- self .cancelAll ();
90
+ if (comptime CANCEL_SUPPORTED ) {
91
+ self .cancelAll ();
92
+ }
85
93
self .io .deinit ();
86
94
self .cancel_pool .deinit ();
87
95
self .timeout_pool .deinit ();
88
96
self .event_callback_pool .deinit ();
97
+ self .cancelled .deinit (self .alloc );
89
98
}
90
99
91
100
// Retrieve all registred I/O events completed by OS kernel,
@@ -156,6 +165,12 @@ pub const SingleThreaded = struct {
156
165
loop .alloc .destroy (completion );
157
166
}
158
167
168
+ if (comptime CANCEL_SUPPORTED == false ) {
169
+ if (loop .cancelled .remove (@intFromPtr (completion ))) {
170
+ return ;
171
+ }
172
+ }
173
+
159
174
// If the loop's context id has changed, don't call the js callback
160
175
// function. The callback's memory has already be cleaned and the
161
176
// events nb reset.
@@ -240,10 +255,22 @@ pub const SingleThreaded = struct {
240
255
}
241
256
242
257
pub fn cancel (self : * Self , id : usize , js_cbk : ? JSCallback ) ! void {
258
+ const alloc = self .alloc ;
259
+ if (comptime CANCEL_SUPPORTED == false ) {
260
+ try self .cancelled .put (alloc , id , {});
261
+ if (js_cbk ) | cbk | {
262
+ var vcbk = cbk ;
263
+ defer vcbk .deinit (alloc );
264
+ vcbk .call (null ) catch {
265
+ self .cbk_error = true ;
266
+ };
267
+ }
268
+ return ;
269
+ }
243
270
const comp_cancel : * IO.Completion = @ptrFromInt (id );
244
271
245
- const completion = try self . alloc .create (Completion );
246
- errdefer self . alloc .destroy (completion );
272
+ const completion = try alloc .create (Completion );
273
+ errdefer alloc .destroy (completion );
247
274
completion .* = undefined ;
248
275
249
276
const ctx = self .alloc .create (ContextCancel ) catch unreachable ;
@@ -267,6 +294,7 @@ pub const SingleThreaded = struct {
267
294
pub fn resetJS (self : * Self ) void {
268
295
self .js_ctx_id += 1 ;
269
296
self .resetEvents (.js );
297
+ self .cancelled .clearRetainingCapacity ();
270
298
}
271
299
272
300
// Reset all existing Zig callbacks.
@@ -431,3 +459,9 @@ const EventCallbackContext = struct {
431
459
ctx : * anyopaque ,
432
460
loop : * SingleThreaded ,
433
461
};
462
+
463
+ const CANCEL_SUPPORTED = switch (builtin .target .os .tag ) {
464
+ .linux = > true ,
465
+ .macos , .tvos , .watchos , .ios = > false ,
466
+ else = > @compileError ("IO is not supported for platform" ),
467
+ };
0 commit comments