authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-22 10:52:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:51-07:00
logd6b0686b055070f390bc3465dbcf678bb590ecae
tree032a786d91626e243f0d699e2d55e1a5a8d85d04
parenta5c309a692f49d205b1e6260ac9c55c9815636eb

std.Io: add Kqueue implementation


3 files changed, 540 insertions(+), 3 deletions(-)

lib/std/Io.zig+1
......@@ -559,6 +559,7 @@ const Io = @This();
559559
560560pub const Evented = switch (builtin.os.tag) {
561561 .linux => @import("Io/IoUring.zig"),
562 .dragonfly, .freebsd, .netbsd, .openbsd, .macos, .ios, .tvos, .visionos, .watchos => @import("Io/Kqueue.zig"),
562563 else => void,
563564};
564565pub const Threaded = @import("Io/Threaded.zig");
lib/std/Io/IoUring.zig+4-3
......@@ -1,9 +1,10 @@
1const std = @import("../std.zig");
1const EventLoop = @This();
22const builtin = @import("builtin");
3
4const std = @import("../std.zig");
5const Io = std.Io;
36const assert = std.debug.assert;
47const Allocator = std.mem.Allocator;
5const Io = std.Io;
6const EventLoop = @This();
78const Alignment = std.mem.Alignment;
89const IoUring = std.os.linux.IoUring;
910
lib/std/Io/Kqueue.zig created+535
......@@ -0,0 +1,535 @@
1const Kqueue = @This();
2const builtin = @import("builtin");
3
4const std = @import("../std.zig");
5const Io = std.Io;
6const Dir = std.Io.Dir;
7const File = std.Io.File;
8const net = std.Io.net;
9const assert = std.debug.assert;
10const Allocator = std.mem.Allocator;
11const Alignment = std.mem.Alignment;
12
13/// Must be a thread-safe allocator.
14gpa: Allocator,
15
16pub fn init(gpa: Allocator) Kqueue {
17 return .{
18 .gpa = gpa,
19 };
20}
21
22pub fn deinit(k: *Kqueue) void {
23 k.* = undefined;
24}
25
26pub fn io(k: *Kqueue) Io {
27 return .{
28 .userdata = k,
29 .vtable = &.{
30 .async = async,
31 .concurrent = concurrent,
32 .await = await,
33 .cancel = cancel,
34 .cancelRequested = cancelRequested,
35 .select = select,
36
37 .groupAsync = groupAsync,
38 .groupWait = groupWait,
39 .groupWaitUncancelable = groupWaitUncancelable,
40 .groupCancel = groupCancel,
41
42 .mutexLock = mutexLock,
43 .mutexLockUncancelable = mutexLockUncancelable,
44 .mutexUnlock = mutexUnlock,
45
46 .conditionWait = conditionWait,
47 .conditionWaitUncancelable = conditionWaitUncancelable,
48 .conditionWake = conditionWake,
49
50 .dirMake = dirMake,
51 .dirMakePath = dirMakePath,
52 .dirMakeOpenPath = dirMakeOpenPath,
53 .dirStat = dirStat,
54 .dirStatPath = dirStatPath,
55
56 .fileStat = fileStat,
57 .dirAccess = dirAccess,
58 .dirCreateFile = dirCreateFile,
59 .dirOpenFile = dirOpenFile,
60 .dirOpenDir = dirOpenDir,
61 .dirClose = dirClose,
62 .fileClose = fileClose,
63 .fileWriteStreaming = fileWriteStreaming,
64 .fileWritePositional = fileWritePositional,
65 .fileReadStreaming = fileReadStreaming,
66 .fileReadPositional = fileReadPositional,
67 .fileSeekBy = fileSeekBy,
68 .fileSeekTo = fileSeekTo,
69 .openSelfExe = openSelfExe,
70
71 .now = now,
72 .sleep = sleep,
73
74 .netListenIp = netListenIp,
75 .netListenUnix = netListenUnix,
76 .netAccept = netAccept,
77 .netBindIp = netBindIp,
78 .netConnectIp = netConnectIp,
79 .netConnectUnix = netConnectUnix,
80 .netClose = netClose,
81 .netRead = netRead,
82 .netWrite = netWrite,
83 .netSend = netSend,
84 .netReceive = netReceive,
85 .netInterfaceNameResolve = netInterfaceNameResolve,
86 .netInterfaceName = netInterfaceName,
87 .netLookup = netLookup,
88 },
89 };
90}
91
92fn async(
93 userdata: ?*anyopaque,
94 result: []u8,
95 result_alignment: std.mem.Alignment,
96 context: []const u8,
97 context_alignment: std.mem.Alignment,
98 start: *const fn (context: *const anyopaque, result: *anyopaque) void,
99) ?*Io.AnyFuture {
100 const k: *Kqueue = @ptrCast(@alignCast(userdata));
101 _ = k;
102 _ = result;
103 _ = result_alignment;
104 _ = context;
105 _ = context_alignment;
106 _ = start;
107 @panic("TODO");
108}
109
110fn concurrent(
111 userdata: ?*anyopaque,
112 result_len: usize,
113 result_alignment: std.mem.Alignment,
114 context: []const u8,
115 context_alignment: std.mem.Alignment,
116 start: *const fn (context: *const anyopaque, result: *anyopaque) void,
117) error{OutOfMemory}!*Io.AnyFuture {
118 const k: *Kqueue = @ptrCast(@alignCast(userdata));
119 _ = k;
120 _ = result_len;
121 _ = result_alignment;
122 _ = context;
123 _ = context_alignment;
124 _ = start;
125 @panic("TODO");
126}
127
128fn await(
129 userdata: ?*anyopaque,
130 any_future: *Io.AnyFuture,
131 result: []u8,
132 result_alignment: std.mem.Alignment,
133) void {
134 const k: *Kqueue = @ptrCast(@alignCast(userdata));
135 _ = k;
136 _ = any_future;
137 _ = result;
138 _ = result_alignment;
139 @panic("TODO");
140}
141
142fn cancel(
143 userdata: ?*anyopaque,
144 any_future: *Io.AnyFuture,
145 result: []u8,
146 result_alignment: std.mem.Alignment,
147) void {
148 const k: *Kqueue = @ptrCast(@alignCast(userdata));
149 _ = k;
150 _ = any_future;
151 _ = result;
152 _ = result_alignment;
153 @panic("TODO");
154}
155
156fn cancelRequested(userdata: ?*anyopaque) bool {
157 const k: *Kqueue = @ptrCast(@alignCast(userdata));
158 _ = k;
159 @panic("TODO");
160}
161
162fn groupAsync(
163 userdata: ?*anyopaque,
164 group: *Io.Group,
165 context: []const u8,
166 context_alignment: std.mem.Alignment,
167 start: *const fn (*Io.Group, context: *const anyopaque) void,
168) void {
169 const k: *Kqueue = @ptrCast(@alignCast(userdata));
170 _ = k;
171 _ = group;
172 _ = context;
173 _ = context_alignment;
174 _ = start;
175 @panic("TODO");
176}
177
178fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) Io.Cancelable!void {
179 const k: *Kqueue = @ptrCast(@alignCast(userdata));
180 _ = k;
181 _ = group;
182 _ = token;
183 @panic("TODO");
184}
185
186fn groupWaitUncancelable(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void {
187 const k: *Kqueue = @ptrCast(@alignCast(userdata));
188 _ = k;
189 _ = group;
190 _ = token;
191 @panic("TODO");
192}
193
194fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void {
195 const k: *Kqueue = @ptrCast(@alignCast(userdata));
196 _ = k;
197 _ = group;
198 _ = token;
199 @panic("TODO");
200}
201
202fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) Io.Cancelable!usize {
203 const k: *Kqueue = @ptrCast(@alignCast(userdata));
204 _ = k;
205 _ = futures;
206 @panic("TODO");
207}
208
209fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) Io.Cancelable!void {
210 const k: *Kqueue = @ptrCast(@alignCast(userdata));
211 _ = k;
212 _ = prev_state;
213 _ = mutex;
214 @panic("TODO");
215}
216fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void {
217 const k: *Kqueue = @ptrCast(@alignCast(userdata));
218 _ = k;
219 _ = prev_state;
220 _ = mutex;
221 @panic("TODO");
222}
223fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void {
224 const k: *Kqueue = @ptrCast(@alignCast(userdata));
225 _ = k;
226 _ = prev_state;
227 _ = mutex;
228 @panic("TODO");
229}
230
231fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void {
232 const k: *Kqueue = @ptrCast(@alignCast(userdata));
233 _ = k;
234 _ = cond;
235 _ = mutex;
236 @panic("TODO");
237}
238fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void {
239 const k: *Kqueue = @ptrCast(@alignCast(userdata));
240 _ = k;
241 _ = cond;
242 _ = mutex;
243 @panic("TODO");
244}
245fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.Wake) void {
246 const k: *Kqueue = @ptrCast(@alignCast(userdata));
247 _ = k;
248 _ = cond;
249 _ = wake;
250 @panic("TODO");
251}
252
253fn dirMake(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void {
254 const k: *Kqueue = @ptrCast(@alignCast(userdata));
255 _ = k;
256 _ = dir;
257 _ = sub_path;
258 _ = mode;
259 @panic("TODO");
260}
261fn dirMakePath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void {
262 const k: *Kqueue = @ptrCast(@alignCast(userdata));
263 _ = k;
264 _ = dir;
265 _ = sub_path;
266 _ = mode;
267 @panic("TODO");
268}
269fn dirMakeOpenPath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.OpenOptions) Dir.MakeOpenPathError!Dir {
270 const k: *Kqueue = @ptrCast(@alignCast(userdata));
271 _ = k;
272 _ = dir;
273 _ = sub_path;
274 _ = options;
275 @panic("TODO");
276}
277fn dirStat(userdata: ?*anyopaque, dir: Dir) Dir.StatError!Dir.Stat {
278 const k: *Kqueue = @ptrCast(@alignCast(userdata));
279 _ = k;
280 _ = dir;
281 @panic("TODO");
282}
283fn dirStatPath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.StatPathOptions) Dir.StatPathError!File.Stat {
284 const k: *Kqueue = @ptrCast(@alignCast(userdata));
285 _ = k;
286 _ = dir;
287 _ = sub_path;
288 _ = options;
289 @panic("TODO");
290}
291fn dirAccess(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.AccessOptions) Dir.AccessError!void {
292 const k: *Kqueue = @ptrCast(@alignCast(userdata));
293 _ = k;
294 _ = dir;
295 _ = sub_path;
296 _ = options;
297 @panic("TODO");
298}
299fn dirCreateFile(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
300 const k: *Kqueue = @ptrCast(@alignCast(userdata));
301 _ = k;
302 _ = dir;
303 _ = sub_path;
304 _ = flags;
305 @panic("TODO");
306}
307fn dirOpenFile(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
308 const k: *Kqueue = @ptrCast(@alignCast(userdata));
309 _ = k;
310 _ = dir;
311 _ = sub_path;
312 _ = flags;
313 @panic("TODO");
314}
315fn dirOpenDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.OpenOptions) Dir.OpenError!Dir {
316 const k: *Kqueue = @ptrCast(@alignCast(userdata));
317 _ = k;
318 _ = dir;
319 _ = sub_path;
320 _ = options;
321 @panic("TODO");
322}
323fn dirClose(userdata: ?*anyopaque, dir: Dir) void {
324 const k: *Kqueue = @ptrCast(@alignCast(userdata));
325 _ = k;
326 _ = dir;
327 @panic("TODO");
328}
329fn fileStat(userdata: ?*anyopaque, file: File) File.StatError!File.Stat {
330 const k: *Kqueue = @ptrCast(@alignCast(userdata));
331 _ = k;
332 _ = file;
333 @panic("TODO");
334}
335fn fileClose(userdata: ?*anyopaque, file: File) void {
336 const k: *Kqueue = @ptrCast(@alignCast(userdata));
337 _ = k;
338 _ = file;
339 @panic("TODO");
340}
341fn fileWriteStreaming(userdata: ?*anyopaque, file: File, buffer: [][]const u8) File.WriteStreamingError!usize {
342 const k: *Kqueue = @ptrCast(@alignCast(userdata));
343 _ = k;
344 _ = file;
345 _ = buffer;
346 @panic("TODO");
347}
348fn fileWritePositional(userdata: ?*anyopaque, file: File, buffer: [][]const u8, offset: u64) File.WritePositionalError!usize {
349 const k: *Kqueue = @ptrCast(@alignCast(userdata));
350 _ = k;
351 _ = file;
352 _ = buffer;
353 _ = offset;
354 @panic("TODO");
355}
356fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: [][]u8) File.ReadStreamingError!usize {
357 const k: *Kqueue = @ptrCast(@alignCast(userdata));
358 _ = k;
359 _ = file;
360 _ = data;
361 @panic("TODO");
362}
363fn fileReadPositional(userdata: ?*anyopaque, file: File, data: [][]u8, offset: u64) File.ReadPositionalError!usize {
364 const k: *Kqueue = @ptrCast(@alignCast(userdata));
365 _ = k;
366 _ = file;
367 _ = data;
368 _ = offset;
369 @panic("TODO");
370}
371fn fileSeekBy(userdata: ?*anyopaque, file: File, relative_offset: i64) File.SeekError!void {
372 const k: *Kqueue = @ptrCast(@alignCast(userdata));
373 _ = k;
374 _ = file;
375 _ = relative_offset;
376 @panic("TODO");
377}
378fn fileSeekTo(userdata: ?*anyopaque, file: File, absolute_offset: u64) File.SeekError!void {
379 const k: *Kqueue = @ptrCast(@alignCast(userdata));
380 _ = k;
381 _ = file;
382 _ = absolute_offset;
383 @panic("TODO");
384}
385fn openSelfExe(userdata: ?*anyopaque, file: File.OpenFlags) File.OpenSelfExeError!File {
386 const k: *Kqueue = @ptrCast(@alignCast(userdata));
387 _ = k;
388 _ = file;
389 @panic("TODO");
390}
391
392fn now(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp {
393 const k: *Kqueue = @ptrCast(@alignCast(userdata));
394 _ = k;
395 _ = clock;
396 @panic("TODO");
397}
398fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
399 const k: *Kqueue = @ptrCast(@alignCast(userdata));
400 _ = k;
401 _ = timeout;
402 @panic("TODO");
403}
404
405fn netListenIp(
406 userdata: ?*anyopaque,
407 address: net.IpAddress,
408 options: net.IpAddress.ListenOptions,
409) net.IpAddress.ListenError!net.Server {
410 const k: *Kqueue = @ptrCast(@alignCast(userdata));
411 _ = k;
412 _ = address;
413 _ = options;
414 @panic("TODO");
415}
416fn netAccept(userdata: ?*anyopaque, server: net.Socket.Handle) net.Server.AcceptError!net.Stream {
417 const k: *Kqueue = @ptrCast(@alignCast(userdata));
418 _ = k;
419 _ = server;
420 @panic("TODO");
421}
422fn netBindIp(userdata: ?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.BindOptions) net.IpAddress.BindError!net.Socket {
423 const k: *Kqueue = @ptrCast(@alignCast(userdata));
424 _ = k;
425 _ = address;
426 _ = options;
427 @panic("TODO");
428}
429fn netConnectIp(userdata: ?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.ConnectOptions) net.IpAddress.ConnectError!net.Stream {
430 const k: *Kqueue = @ptrCast(@alignCast(userdata));
431 _ = k;
432 _ = address;
433 _ = options;
434 @panic("TODO");
435}
436fn netListenUnix(
437 userdata: ?*anyopaque,
438 unix_address: *const net.UnixAddress,
439 options: net.UnixAddress.ListenOptions,
440) net.UnixAddress.ListenError!net.Socket.Handle {
441 const k: *Kqueue = @ptrCast(@alignCast(userdata));
442 _ = k;
443 _ = unix_address;
444 _ = options;
445 @panic("TODO");
446}
447fn netConnectUnix(
448 userdata: ?*anyopaque,
449 unix_address: *const net.UnixAddress,
450) net.UnixAddress.ConnectError!net.Socket.Handle {
451 const k: *Kqueue = @ptrCast(@alignCast(userdata));
452 _ = k;
453 _ = unix_address;
454 @panic("TODO");
455}
456fn netSend(
457 userdata: ?*anyopaque,
458 handle: net.Socket.Handle,
459 outgoing_messages: []net.OutgoingMessage,
460 flags: net.SendFlags,
461) struct { ?net.Socket.SendError, usize } {
462 const k: *Kqueue = @ptrCast(@alignCast(userdata));
463 _ = k;
464 _ = handle;
465 _ = outgoing_messages;
466 _ = flags;
467 @panic("TODO");
468}
469fn netReceive(
470 userdata: ?*anyopaque,
471 handle: net.Socket.Handle,
472 message_buffer: []net.IncomingMessage,
473 data_buffer: []u8,
474 flags: net.ReceiveFlags,
475 timeout: Io.Timeout,
476) struct { ?net.Socket.ReceiveTimeoutError, usize } {
477 const k: *Kqueue = @ptrCast(@alignCast(userdata));
478 _ = k;
479 _ = handle;
480 _ = message_buffer;
481 _ = data_buffer;
482 _ = flags;
483 _ = timeout;
484 @panic("TODO");
485}
486fn netRead(userdata: ?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
487 const k: *Kqueue = @ptrCast(@alignCast(userdata));
488 _ = k;
489 _ = src;
490 _ = data;
491 @panic("TODO");
492}
493fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize {
494 const k: *Kqueue = @ptrCast(@alignCast(userdata));
495 _ = k;
496 _ = dest;
497 _ = header;
498 _ = data;
499 _ = splat;
500 @panic("TODO");
501}
502fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void {
503 const k: *Kqueue = @ptrCast(@alignCast(userdata));
504 _ = k;
505 _ = handle;
506 @panic("TODO");
507}
508fn netInterfaceNameResolve(
509 userdata: ?*anyopaque,
510 name: *const net.Interface.Name,
511) net.Interface.Name.ResolveError!net.Interface {
512 const k: *Kqueue = @ptrCast(@alignCast(userdata));
513 _ = k;
514 _ = name;
515 @panic("TODO");
516}
517fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name {
518 const k: *Kqueue = @ptrCast(@alignCast(userdata));
519 _ = k;
520 _ = interface;
521 @panic("TODO");
522}
523fn netLookup(
524 userdata: ?*anyopaque,
525 host_name: net.HostName,
526 result: *Io.Queue(net.HostName.LookupResult),
527 options: net.HostName.LookupOptions,
528) void {
529 const k: *Kqueue = @ptrCast(@alignCast(userdata));
530 _ = k;
531 _ = host_name;
532 _ = result;
533 _ = options;
534 @panic("TODO");
535}