Skip to content

Commit a2ca84e

Browse files
committed
Round out PollEvents
1 parent 980a71f commit a2ca84e

2 files changed

Lines changed: 62 additions & 18 deletions

File tree

Sources/System/IORing/PollEvents.swift

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ extension IORing.Request {
1414
///
1515
/// `PollEvents` represents the event mask used with io_uring poll
1616
/// operations to specify which I/O conditions to monitor on a file
17-
/// descriptor. These events correspond to the standard Posix poll events
17+
/// descriptor. These events correspond to the standard POSIX poll events
1818
/// defined in the kernel's `poll.h` header.
1919
///
2020
/// Use `PollEvents` with
@@ -32,30 +32,80 @@ extension IORing.Request {
3232
/// isMultiShot: true
3333
/// )
3434
/// ```
35-
public struct PollEvents: OptionSet, Hashable, Codable {
35+
public struct PollEvents: OptionSet, Hashable, Codable, CaseIterable {
3636
public var rawValue: UInt32
3737

3838
@inlinable
3939
public init(rawValue: UInt32) {
4040
self.rawValue = rawValue
4141
}
4242

43+
@usableFromInline
44+
init(_ event: Event) {
45+
self.rawValue = event.rawValue
46+
}
47+
48+
@usableFromInline
49+
enum Event: UInt32, RawRepresentable, Hashable, CaseIterable {
50+
case pollIn = 0x0001
51+
case pollOut = 0x0004
52+
case pollErr = 0x0008
53+
case pollHup = 0x0010
54+
case pollNval = 0x0020
55+
}
56+
57+
public static var allCases: [PollEvents] {
58+
Event.allCases.map(PollEvents.init(_:))
59+
}
60+
4361
/// An event indicating data is available for reading.
4462
///
4563
/// This event becomes active when data arrives on the file descriptor
4664
/// and can be read without blocking. For sockets, this includes when
4765
/// a new connection is available on a listening socket. Corresponds
48-
/// to the Posix `POLLIN` event flag.
66+
/// to the POSIX `POLLIN` event flag.
4967
@inlinable
50-
public static var pollIn: PollEvents { PollEvents(rawValue: 0x0001) }
68+
public static var pollIn: PollEvents { PollEvents(.pollIn) }
5169

5270
/// An event indicating the file descriptor is ready for writing.
5371
///
5472
/// This event becomes active when writing to the file descriptor will
5573
/// not block. For sockets, this indicates that send buffer space is
56-
/// available. Corresponds to the Posix `POLLOUT` event flag.
74+
/// available. Corresponds to the POSIX `POLLOUT` event flag.
5775
@inlinable
58-
public static var pollOut: PollEvents { PollEvents(rawValue: 0x0004) }
76+
public static var pollOut: PollEvents { PollEvents(.pollOut) }
77+
78+
/// An event indicating an error condition on the file descriptor.
79+
///
80+
/// The kernel reports this event whether or not it was requested, so
81+
/// it can appear in a completion's result mask even when the poll
82+
/// asked only for ``pollIn`` or ``pollOut``. Requesting it explicitly
83+
/// has no effect. Corresponds to the POSIX `POLLERR` event flag.
84+
@_alwaysEmitIntoClient
85+
public static var pollErr: PollEvents { PollEvents(.pollErr) }
86+
87+
/// An event indicating the peer closed its end of the channel.
88+
///
89+
/// For a pipe this means the writing end was closed; for a socket, that
90+
/// the connection was shut down. A descriptor reporting this event will
91+
/// never become readable again, so treating it as "not ready yet" and
92+
/// polling again will not make progress.
93+
///
94+
/// The kernel reports this event whether or not it was requested, and
95+
/// requesting it explicitly has no effect. Corresponds to the POSIX
96+
/// `POLLHUP` event flag.
97+
@_alwaysEmitIntoClient
98+
public static var pollHup: PollEvents { PollEvents(.pollHup) }
99+
100+
/// An event indicating the file descriptor is not open.
101+
///
102+
/// This usually means the descriptor was closed, or was never valid.
103+
///
104+
/// The kernel reports this event whether or not it was requested, and
105+
/// requesting it explicitly has no effect. Corresponds to the POSIX
106+
/// `POLLNVAL` event flag.
107+
@_alwaysEmitIntoClient
108+
public static var pollNval: PollEvents { PollEvents(.pollNval) }
59109
}
60110
}
61111
#endif

Tests/SystemTests/IORingTests.swift

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ final class IORingTests: XCTestCase {
505505
}
506506
}
507507

508-
func testUnexpectedPollValue() throws {
508+
func testPollHangup() throws {
509509
try XCTSkipIf(!uringEnabled, failureMessage)
510510
var ring = try IORing(queueDepth: 8)
511511
let (readFD, writeFD) = try FileDescriptor.pipe()
@@ -529,21 +529,15 @@ final class IORingTests: XCTestCase {
529529
let dt = Duration.seconds(1)
530530
let completion = try ring.blockingConsumeCompletion(timeout: dt)
531531

532-
let values = [ // This should be caseIterable.
533-
IORing.Request.PollEvents.pollIn.rawValue,
534-
IORing.Request.PollEvents.pollOut.rawValue
535-
]
536-
537-
for value in values {
538-
if completion.result & Int32(value) != 0 {
539-
// success!
532+
for event in IORing.Request.PollEvents.allCases {
533+
if completion.result & Int32(event.rawValue) != 0 {
534+
XCTAssertEqual(event, .pollHup)
540535
return
541536
}
542537
}
543538

544-
let pollValue = completion.result & 0x10
545-
XCTAssertEqual(pollValue, 0x10)
546-
XCTFail("Unexpected poll event: 0x\(String(pollValue, radix: 16))")
539+
let unexpected = completion.result
540+
XCTFail("Unexpected poll event: 0x\(String(unexpected, radix: 16))")
547541
}
548542
}
549543
#endif // os(Linux)

0 commit comments

Comments
 (0)