const std = @import("std"); const posix = std.posix; /// Event signaling using Linux eventfd /// Allows efficient cross-thread event notification without polling pub const EventFd = struct { fd: posix.fd_t, pub const Error = error{ EventFdCreateFailed, }; /// Create a new eventfd pub fn init() Error!EventFd { // EFD_NONBLOCK | EFD_CLOEXEC const flags: u32 = 0x800 | 0x80000; const fd = std.os.linux.eventfd(0, flags); if (@as(isize, @bitCast(fd)) < 0) { return error.EventFdCreateFailed; } return .{ .fd = @intCast(fd) }; } pub fn deinit(self: *EventFd) void { posix.close(self.fd); } /// Signal the event (non-blocking) pub fn signal(self: *EventFd) void { const val: u64 = 1; _ = posix.write(self.fd, std.mem.asBytes(&val)) catch {}; } /// Consume the event (non-blocking, returns true if event was pending) pub fn consume(self: *EventFd) bool { var val: u64 = undefined; const n = posix.read(self.fd, std.mem.asBytes(&val)) catch return false; return n == 8; } /// Get the file descriptor for polling pub fn getFd(self: *EventFd) posix.fd_t { return self.fd; } }; /// Global eventfd for denylist reload signaling var denylist_event: ?EventFd = null; /// Initialize the global denylist event pub fn initDenylistEvent() !void { denylist_event = try EventFd.init(); } /// Deinitialize the global denylist event pub fn deinitDenylistEvent() void { if (denylist_event) |*ev| { ev.deinit(); denylist_event = null; } } /// Signal that denylist needs reload pub fn signalDenylistReload() void { if (denylist_event) |*ev| { ev.signal(); } } /// Get the denylist event fd for polling (returns -1 if not initialized) pub fn getDenylistEventFd() posix.fd_t { if (denylist_event) |*ev| { return ev.getFd(); } return -1; } /// Consume the denylist reload event pub fn consumeDenylistReload() bool { if (denylist_event) |*ev| { return ev.consume(); } return false; }