diff --git a/lib/std/Io.zig b/lib/std/Io.zig index a3cb2cf29f..d89f2d23af 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -559,6 +559,7 @@ const Io = @This(); pub const Evented = switch (builtin.os.tag) { .linux => @import("Io/IoUring.zig"), + .dragonfly, .freebsd, .netbsd, .openbsd, .macos, .ios, .tvos, .visionos, .watchos => @import("Io/Kqueue.zig"), else => void, }; pub const Threaded = @import("Io/Threaded.zig"); diff --git a/lib/std/Io/IoUring.zig b/lib/std/Io/IoUring.zig index c6dca1597d..43ce8e1c0d 100644 --- a/lib/std/Io/IoUring.zig +++ b/lib/std/Io/IoUring.zig @@ -1,9 +1,10 @@ -const std = @import("../std.zig"); +const EventLoop = @This(); const builtin = @import("builtin"); + +const std = @import("../std.zig"); +const Io = std.Io; const assert = std.debug.assert; const Allocator = std.mem.Allocator; -const Io = std.Io; -const EventLoop = @This(); const Alignment = std.mem.Alignment; const IoUring = std.os.linux.IoUring; diff --git a/lib/std/Io/Kqueue.zig b/lib/std/Io/Kqueue.zig new file mode 100644 index 0000000000..edfa76cd5e --- /dev/null +++ b/lib/std/Io/Kqueue.zig @@ -0,0 +1,535 @@ +const Kqueue = @This(); +const builtin = @import("builtin"); + +const std = @import("../std.zig"); +const Io = std.Io; +const Dir = std.Io.Dir; +const File = std.Io.File; +const net = std.Io.net; +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const Alignment = std.mem.Alignment; + +/// Must be a thread-safe allocator. +gpa: Allocator, + +pub fn init(gpa: Allocator) Kqueue { + return .{ + .gpa = gpa, + }; +} + +pub fn deinit(k: *Kqueue) void { + k.* = undefined; +} + +pub fn io(k: *Kqueue) Io { + return .{ + .userdata = k, + .vtable = &.{ + .async = async, + .concurrent = concurrent, + .await = await, + .cancel = cancel, + .cancelRequested = cancelRequested, + .select = select, + + .groupAsync = groupAsync, + .groupWait = groupWait, + .groupWaitUncancelable = groupWaitUncancelable, + .groupCancel = groupCancel, + + .mutexLock = mutexLock, + .mutexLockUncancelable = mutexLockUncancelable, + .mutexUnlock = mutexUnlock, + + .conditionWait = conditionWait, + .conditionWaitUncancelable = conditionWaitUncancelable, + .conditionWake = conditionWake, + + .dirMake = dirMake, + .dirMakePath = dirMakePath, + .dirMakeOpenPath = dirMakeOpenPath, + .dirStat = dirStat, + .dirStatPath = dirStatPath, + + .fileStat = fileStat, + .dirAccess = dirAccess, + .dirCreateFile = dirCreateFile, + .dirOpenFile = dirOpenFile, + .dirOpenDir = dirOpenDir, + .dirClose = dirClose, + .fileClose = fileClose, + .fileWriteStreaming = fileWriteStreaming, + .fileWritePositional = fileWritePositional, + .fileReadStreaming = fileReadStreaming, + .fileReadPositional = fileReadPositional, + .fileSeekBy = fileSeekBy, + .fileSeekTo = fileSeekTo, + .openSelfExe = openSelfExe, + + .now = now, + .sleep = sleep, + + .netListenIp = netListenIp, + .netListenUnix = netListenUnix, + .netAccept = netAccept, + .netBindIp = netBindIp, + .netConnectIp = netConnectIp, + .netConnectUnix = netConnectUnix, + .netClose = netClose, + .netRead = netRead, + .netWrite = netWrite, + .netSend = netSend, + .netReceive = netReceive, + .netInterfaceNameResolve = netInterfaceNameResolve, + .netInterfaceName = netInterfaceName, + .netLookup = netLookup, + }, + }; +} + +fn async( + userdata: ?*anyopaque, + result: []u8, + result_alignment: std.mem.Alignment, + context: []const u8, + context_alignment: std.mem.Alignment, + start: *const fn (context: *const anyopaque, result: *anyopaque) void, +) ?*Io.AnyFuture { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = result; + _ = result_alignment; + _ = context; + _ = context_alignment; + _ = start; + @panic("TODO"); +} + +fn concurrent( + userdata: ?*anyopaque, + result_len: usize, + result_alignment: std.mem.Alignment, + context: []const u8, + context_alignment: std.mem.Alignment, + start: *const fn (context: *const anyopaque, result: *anyopaque) void, +) error{OutOfMemory}!*Io.AnyFuture { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = result_len; + _ = result_alignment; + _ = context; + _ = context_alignment; + _ = start; + @panic("TODO"); +} + +fn await( + userdata: ?*anyopaque, + any_future: *Io.AnyFuture, + result: []u8, + result_alignment: std.mem.Alignment, +) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = any_future; + _ = result; + _ = result_alignment; + @panic("TODO"); +} + +fn cancel( + userdata: ?*anyopaque, + any_future: *Io.AnyFuture, + result: []u8, + result_alignment: std.mem.Alignment, +) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = any_future; + _ = result; + _ = result_alignment; + @panic("TODO"); +} + +fn cancelRequested(userdata: ?*anyopaque) bool { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + @panic("TODO"); +} + +fn groupAsync( + userdata: ?*anyopaque, + group: *Io.Group, + context: []const u8, + context_alignment: std.mem.Alignment, + start: *const fn (*Io.Group, context: *const anyopaque) void, +) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = group; + _ = context; + _ = context_alignment; + _ = start; + @panic("TODO"); +} + +fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) Io.Cancelable!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = group; + _ = token; + @panic("TODO"); +} + +fn groupWaitUncancelable(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = group; + _ = token; + @panic("TODO"); +} + +fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = group; + _ = token; + @panic("TODO"); +} + +fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) Io.Cancelable!usize { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = futures; + @panic("TODO"); +} + +fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) Io.Cancelable!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = prev_state; + _ = mutex; + @panic("TODO"); +} +fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = prev_state; + _ = mutex; + @panic("TODO"); +} +fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = prev_state; + _ = mutex; + @panic("TODO"); +} + +fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = cond; + _ = mutex; + @panic("TODO"); +} +fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = cond; + _ = mutex; + @panic("TODO"); +} +fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.Wake) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = cond; + _ = wake; + @panic("TODO"); +} + +fn dirMake(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + _ = sub_path; + _ = mode; + @panic("TODO"); +} +fn dirMakePath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + _ = sub_path; + _ = mode; + @panic("TODO"); +} +fn dirMakeOpenPath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.OpenOptions) Dir.MakeOpenPathError!Dir { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + _ = sub_path; + _ = options; + @panic("TODO"); +} +fn dirStat(userdata: ?*anyopaque, dir: Dir) Dir.StatError!Dir.Stat { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + @panic("TODO"); +} +fn dirStatPath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.StatPathOptions) Dir.StatPathError!File.Stat { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + _ = sub_path; + _ = options; + @panic("TODO"); +} +fn dirAccess(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.AccessOptions) Dir.AccessError!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + _ = sub_path; + _ = options; + @panic("TODO"); +} +fn dirCreateFile(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + _ = sub_path; + _ = flags; + @panic("TODO"); +} +fn dirOpenFile(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + _ = sub_path; + _ = flags; + @panic("TODO"); +} +fn dirOpenDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.OpenOptions) Dir.OpenError!Dir { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + _ = sub_path; + _ = options; + @panic("TODO"); +} +fn dirClose(userdata: ?*anyopaque, dir: Dir) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dir; + @panic("TODO"); +} +fn fileStat(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + @panic("TODO"); +} +fn fileClose(userdata: ?*anyopaque, file: File) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + @panic("TODO"); +} +fn fileWriteStreaming(userdata: ?*anyopaque, file: File, buffer: [][]const u8) File.WriteStreamingError!usize { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + _ = buffer; + @panic("TODO"); +} +fn fileWritePositional(userdata: ?*anyopaque, file: File, buffer: [][]const u8, offset: u64) File.WritePositionalError!usize { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + _ = buffer; + _ = offset; + @panic("TODO"); +} +fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: [][]u8) File.ReadStreamingError!usize { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + _ = data; + @panic("TODO"); +} +fn fileReadPositional(userdata: ?*anyopaque, file: File, data: [][]u8, offset: u64) File.ReadPositionalError!usize { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + _ = data; + _ = offset; + @panic("TODO"); +} +fn fileSeekBy(userdata: ?*anyopaque, file: File, relative_offset: i64) File.SeekError!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + _ = relative_offset; + @panic("TODO"); +} +fn fileSeekTo(userdata: ?*anyopaque, file: File, absolute_offset: u64) File.SeekError!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + _ = absolute_offset; + @panic("TODO"); +} +fn openSelfExe(userdata: ?*anyopaque, file: File.OpenFlags) File.OpenSelfExeError!File { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = file; + @panic("TODO"); +} + +fn now(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = clock; + @panic("TODO"); +} +fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = timeout; + @panic("TODO"); +} + +fn netListenIp( + userdata: ?*anyopaque, + address: net.IpAddress, + options: net.IpAddress.ListenOptions, +) net.IpAddress.ListenError!net.Server { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = address; + _ = options; + @panic("TODO"); +} +fn netAccept(userdata: ?*anyopaque, server: net.Socket.Handle) net.Server.AcceptError!net.Stream { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = server; + @panic("TODO"); +} +fn netBindIp(userdata: ?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.BindOptions) net.IpAddress.BindError!net.Socket { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = address; + _ = options; + @panic("TODO"); +} +fn netConnectIp(userdata: ?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.ConnectOptions) net.IpAddress.ConnectError!net.Stream { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = address; + _ = options; + @panic("TODO"); +} +fn netListenUnix( + userdata: ?*anyopaque, + unix_address: *const net.UnixAddress, + options: net.UnixAddress.ListenOptions, +) net.UnixAddress.ListenError!net.Socket.Handle { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = unix_address; + _ = options; + @panic("TODO"); +} +fn netConnectUnix( + userdata: ?*anyopaque, + unix_address: *const net.UnixAddress, +) net.UnixAddress.ConnectError!net.Socket.Handle { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = unix_address; + @panic("TODO"); +} +fn netSend( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + outgoing_messages: []net.OutgoingMessage, + flags: net.SendFlags, +) struct { ?net.Socket.SendError, usize } { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = handle; + _ = outgoing_messages; + _ = flags; + @panic("TODO"); +} +fn netReceive( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + message_buffer: []net.IncomingMessage, + data_buffer: []u8, + flags: net.ReceiveFlags, + timeout: Io.Timeout, +) struct { ?net.Socket.ReceiveTimeoutError, usize } { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = handle; + _ = message_buffer; + _ = data_buffer; + _ = flags; + _ = timeout; + @panic("TODO"); +} +fn netRead(userdata: ?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = src; + _ = data; + @panic("TODO"); +} +fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = dest; + _ = header; + _ = data; + _ = splat; + @panic("TODO"); +} +fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = handle; + @panic("TODO"); +} +fn netInterfaceNameResolve( + userdata: ?*anyopaque, + name: *const net.Interface.Name, +) net.Interface.Name.ResolveError!net.Interface { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = name; + @panic("TODO"); +} +fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = interface; + @panic("TODO"); +} +fn netLookup( + userdata: ?*anyopaque, + host_name: net.HostName, + result: *Io.Queue(net.HostName.LookupResult), + options: net.HostName.LookupOptions, +) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = host_name; + _ = result; + _ = options; + @panic("TODO"); +}