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 }