lib/sys/src/poll.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const builtin = @import("builtin");
3 const capabilities = @import("capabilities.zig");
4
5 const native_os = builtin.os.tag;
6 const posix = std.posix;
7
8 pub const required_capabilities = switch (native_os) {
9 .linux => capabilities.noLibc(&.{ .descriptors, .event_loop }),
10 else => capabilities.host(&.{ .descriptors, .event_loop }),
11 };
12
13 pub const Descriptor = posix.pollfd;
14 pub const TimeSpec = posix.timespec;
15 pub const SignalSet = posix.sigset_t;
16 pub const WaitError = posix.PollError || error{UnsupportedPlatform};
17 pub const PreciseWaitError = posix.PPollError || error{UnsupportedPlatform};
18
19 pub const Event = struct {
20 pub const input = posix.POLL.IN;
21 pub const output = posix.POLL.OUT;
22 pub const error_condition = posix.POLL.ERR;
23 pub const hangup = posix.POLL.HUP;
24 pub const invalid = posix.POLL.NVAL;
25 };
26
27 pub fn wait(descriptors: []Descriptor, timeout_ms: i32) WaitError!usize {
28 if (comptime !supported()) return error.UnsupportedPlatform;
29 return posix.poll(descriptors, timeout_ms);
30 }
31
32 pub fn waitPrecise(
33 descriptors: []Descriptor,
34 timeout: ?*const TimeSpec,
35 signal_mask: ?*const SignalSet,
36 ) PreciseWaitError!usize {
37 if (comptime !preciseSupported()) return error.UnsupportedPlatform;
38 return posix.ppoll(descriptors, timeout, signal_mask);
39 }
40
41 /// Whether `waitPrecise` runs here. Apple's libc has no `ppoll`.
42 pub fn preciseSupported() bool {
43 return supported() and !native_os.isDarwin();
44 }
45
46 pub fn supported() bool {
47 return switch (native_os) {
48 .windows, .wasi, .freestanding => false,
49 else => true,
50 };
51 }
52
53 test "poll waits preserve descriptor readiness" {
54 if (!supported()) return error.SkipZigTest;
55 const fd = @import("fd.zig");
56 const descriptors = try fd.pipeWithOptions(.{});
57 defer fd.close(descriptors[0]);
58 defer fd.close(descriptors[1]);
59
60 var poll_descriptors = [_]Descriptor{.{
61 .fd = descriptors[0],
62 .events = Event.input,
63 .revents = 0,
64 }};
65 try std.testing.expectEqual(@as(usize, 0), try wait(&poll_descriptors, 0));
66 try std.testing.expectEqual(@as(usize, 1), try fd.write(descriptors[1], "x"));
67 try std.testing.expectEqual(@as(usize, 1), try wait(&poll_descriptors, 0));
68
69 if (!preciseSupported()) return;
70 const timeout = TimeSpec{ .sec = 0, .nsec = 0 };
71 try std.testing.expectEqual(
72 @as(usize, 1),
73 try waitPrecise(&poll_descriptors, &timeout, null),
74 );
75 }