Skip to content

Commit

Permalink
fix: add xev.zig, lib.zig
Browse files Browse the repository at this point in the history
  • Loading branch information
robbielyman committed Sep 22, 2024
1 parent f5977bd commit 2127b0f
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 0 deletions.
136 changes: 136 additions & 0 deletions src/lib.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
const std = @import("std");
const builtin = @import("builtin");

pub const Xev = @import("xev.zig").Xev;

/// System-specific interfaces. Note that they are always pub for
/// all systems but if you reference them and force them to be analyzed
/// the proper system APIs must exist. Due to Zig's lazy analysis, if you
/// don't use any interface it will NOT be compiled (yay!).
pub const IO_Uring = Xev(.io_uring, @import("backend/io_uring.zig"));
pub const Epoll = Xev(.epoll, @import("backend/epoll.zig"));
pub const Kqueue = Xev(.kqueue, @import("backend/kqueue.zig"));
pub const WasiPoll = Xev(.wasi_poll, @import("backend/wasi_poll.zig"));
pub const IOCP = Xev(.iocp, @import("backend/iocp.zig"));

/// Generic thread pool implementation.
pub const ThreadPool = @import("ThreadPool.zig");

/// This stream (lowercase s) can be used as a namespace to access
/// Closeable, Writeable, Readable, etc. so that custom streams
/// can be constructed.
pub const stream = @import("watcher/stream.zig");

/// The backend types.
pub const Backend = enum {
io_uring,
epoll,
kqueue,
wasi_poll,
iocp,

/// Returns a recommend default backend from inspecting the system.
pub fn default() Backend {
return @as(?Backend, switch (builtin.os.tag) {
.linux => .io_uring,
.ios, .macos => .kqueue,
.wasi => .wasi_poll,
.windows => .iocp,
else => null,
}) orelse {
@compileLog(builtin.os);
@compileError("no default backend for this target");
};
}

/// Returns the Api (return value of Xev) for the given backend type.
pub fn Api(comptime self: Backend) type {
return switch (self) {
.io_uring => IO_Uring,
.epoll => Epoll,
.kqueue => Kqueue,
.wasi_poll => WasiPoll,
.iocp => IOCP,
};
}
};

pub const backend = Backend.default();

pub const Sys = backend.Api().Sys;

const loop = @import("loop.zig");

/// The core loop APIs.
pub const Loop = Sys.Loop;
pub const Completion = Sys.Completion;
pub const Result = Sys.Result;
pub const ReadBuffer = Sys.ReadBuffer;
pub const WriteBuffer = Sys.WriteBuffer;
pub const Options = loop.Options;
pub const RunMode = loop.RunMode;
pub const CallbackAction = loop.CallbackAction;
pub const CompletionState = loop.CompletionState;

/// Error types
pub const AcceptError = Sys.AcceptError;
pub const CancelError = Sys.CancelError;
pub const CloseError = Sys.CloseEror;
pub const ConnectError = Sys.ConnectError;
pub const ShutdownError = Sys.ShutdownError;
pub const WriteError = Sys.WriteError;
pub const ReadError = Sys.ReadError;

const Self = @This();

/// The high-level helper interfaces that make it easier to perform
/// common tasks. These may not work with all possible Loop implementations.
pub const Async = @import("watcher/async.zig").Async(Self);
pub const File = @import("watcher/file.zig").File(Self);
pub const Process = @import("watcher/process.zig").Process(Self);
pub const Stream = stream.GenericStream(Self);
pub const Timer = @import("watcher/timer.zig").Timer(Self);
pub const TCP = @import("watcher/tcp.zig").TCP(Self);
pub const UDP = @import("watcher/udp.zig").UDP(Self);

/// The callback of the main Loop operations. Higher level interfaces may
/// use a different callback mechanism.
pub const Callback = *const fn (
userdata: ?*anyopaque,
loop: *Loop,
completion: *Completion,
result: Result,
) CallbackAction;

pub const noopCallback = Sys.noopCallback;

test {
// Tested on all platforms
_ = @import("heap.zig");
_ = @import("queue.zig");
_ = @import("queue_mpsc.zig");
_ = ThreadPool;

// Test the C API
if (builtin.os.tag != .wasi) _ = @import("c_api.zig");

// OS-specific tests
switch (builtin.os.tag) {
.linux => {
_ = Epoll;
_ = IO_Uring;
_ = @import("linux/timerfd.zig");
},

.wasi => {
//_ = WasiPoll;
_ = @import("backend/wasi_poll.zig");
},

.windows => {
_ = @import("backend/iocp.zig");
},

else => {},
}
}
75 changes: 75 additions & 0 deletions src/xev.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const Backend = @import("lib.zig").Backend;

pub fn Xev(comptime be: Backend, comptime T: type) type {
return struct {
const Self = @This();
const loop = @import("loop.zig");

/// The backend that this is. This is supplied at comptime so
/// it is up to the caller to say the right thing. This lets custom
/// implementations also "quack" like an implementation.
pub const backend = be;

/// The core loop APIs.
pub const Loop = T.Loop;
pub const Completion = T.Completion;
pub const Result = T.Result;
pub const ReadBuffer = T.ReadBuffer;
pub const WriteBuffer = T.WriteBuffer;
pub const Options = loop.Options;
pub const RunMode = loop.RunMode;
pub const CallbackAction = loop.CallbackAction;
pub const CompletionState = loop.CompletionState;

/// Error types
pub const AcceptError = T.AcceptError;
pub const CancelError = T.CancelError;
pub const CloseError = T.CloseError;
pub const ConnectError = T.ConnectError;
pub const ShutdownError = T.ShutdownError;
pub const WriteError = T.WriteError;
pub const ReadError = T.ReadError;

/// The high-level helper interfaces that make it easier to perform
/// common tasks. These may not work with all possible Loop implementations.
pub const Async = @import("watcher/async.zig").Async(Self);
pub const File = @import("watcher/file.zig").File(Self);
pub const Process = @import("watcher/process.zig").Process(Self);
pub const Stream = @import("watcher/stream.zig").GenericStream(Self);
pub const Timer = @import("watcher/timer.zig").Timer(Self);
pub const TCP = @import("watcher/tcp.zig").TCP(Self);
pub const UDP = @import("watcher/udp.zig").UDP(Self);

/// The callback of the main Loop operations. Higher level interfaces may
/// use a different callback mechanism.
pub const Callback = *const fn (
userdata: ?*anyopaque,
loop: *Loop,
completion: *Completion,
result: Result,
) CallbackAction;

/// A way to access the raw type.
pub const Sys = T;

/// A callback that does nothing and immediately disarms. This
/// implements xev.Callback and is the default value for completions.
pub fn noopCallback(
_: ?*anyopaque,
_: *Loop,
_: *Completion,
_: Result,
) CallbackAction {
return .disarm;
}

test {
@import("std").testing.refAllDecls(@This());
}

test "completion is zero-able" {
const c: Completion = .{};
_ = c;
}
};
}

0 comments on commit 2127b0f

Please sign in to comment.