-
Notifications
You must be signed in to change notification settings - Fork 135
[IO_URING] Add support for pollAdd operation
#273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,12 @@ internal enum IORequestCore { | |
| intoSlot: IORing.RegisteredFile, | ||
| context: UInt64 = 0 | ||
| ) | ||
| case pollAdd( | ||
| file: FileDescriptor, | ||
| pollEvents: IORing.Request.PollEvents, | ||
| isMultiShot: Bool = true, | ||
| context: UInt64 = 0 | ||
| ) | ||
| case read( | ||
| file: FileDescriptor, | ||
| buffer: IORing.RegisteredBuffer, | ||
|
|
@@ -187,6 +193,72 @@ extension IORing.Request { | |
| .init(core: .nop) | ||
| } | ||
|
|
||
| /// Adds a poll operation to monitor a file descriptor for specific I/O events. | ||
| /// | ||
| /// This method creates an io_uring poll operation that monitors the specified file descriptor | ||
| /// for I/O readiness events. The operation completes when any of the requested events become | ||
| /// active on the file descriptor, such as data becoming available for reading or the descriptor | ||
FranzBusch marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /// becoming ready for writing. | ||
| /// | ||
| /// Poll operations are useful for implementing efficient I/O multiplexing, allowing you to | ||
| /// monitor multiple file descriptors concurrently within a single io_uring instance. When used | ||
| /// with multishot mode, a single poll operation can deliver multiple completion events without | ||
| /// needing to be resubmitted. | ||
| /// | ||
| /// ## Multishot Behavior | ||
| /// | ||
| /// When `isMultiShot` is `true`, the poll operation automatically rearms after each completion | ||
| /// event, continuing to monitor the file descriptor for subsequent events. This reduces | ||
| /// submission overhead for long-lived monitoring operations. The operation continues until | ||
| /// explicitly cancelled or the file descriptor is closed. | ||
| /// | ||
| /// When `isMultiShot` is `false`, the poll operation completes once after the first matching | ||
| /// event occurs, requiring resubmission to continue monitoring. | ||
| /// | ||
| /// ## Example Usage | ||
| /// | ||
| /// ```swift | ||
| /// // Monitor a socket for incoming connections | ||
| /// let pollRequest = IORing.Request.pollAdd( | ||
| /// listenSocket, | ||
| /// pollEvents: .pollin, | ||
| /// isMultiShot: true, | ||
| /// context: 1 | ||
| /// ) | ||
| /// try ring.submit(pollRequest) | ||
| /// | ||
| /// // Process completions | ||
| /// for completion in try ring.completions() { | ||
| /// if completion.context == 1 { | ||
| /// // Handle incoming connection | ||
| /// } | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// - Parameters: | ||
| /// - file: The file descriptor to monitor for I/O events. | ||
| /// - pollEvents: The I/O events to monitor on the file descriptor. | ||
| /// - isMultiShot: If `true`, the poll operation automatically rearms after each event, | ||
| /// continuing to monitor the file descriptor. If `false`, the operation completes after | ||
| /// the first matching event. Defaults to `false`. | ||
| /// - context: An application-specific value passed through to the completion event, | ||
| /// allowing you to identify which operation completed. Defaults to `0`. | ||
| /// | ||
| /// - Returns: An I/O ring request that monitors the file descriptor for the specified events. | ||
| /// | ||
| /// ## See Also | ||
| /// | ||
| /// - ``PollEvents``: The events that can be monitored. | ||
| /// - ``IORing/Request/cancel(_:matching:)``: Cancelling poll operations. | ||
| @inlinable public static func pollAdd( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typically Swift naming style would be verb-first but if there's a good reason to have it this way it's probably fine
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was trying to match what the io_uring operation was called. I wasn't sure how much we tried to change the naming to fit our Swift naming guidelines.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guessed that was probably what you were doing. I remember this coming up during the initial proposal review and iirc folks leaned "don't try to make the names friendlier" so that looking up docs will work better. I'm still torn on it but I see the logic.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me know what you prefer and I am happy to change if needed. I am open to both. |
||
| _ file: FileDescriptor, | ||
| pollEvents: PollEvents, | ||
| isMultiShot: Bool = false, | ||
| context: UInt64 = 0 | ||
| ) -> IORing.Request { | ||
| .init(core: .pollAdd(file: file, pollEvents: pollEvents, isMultiShot: isMultiShot, context: context)) | ||
| } | ||
|
|
||
| @inlinable public static func read( | ||
| _ file: IORing.RegisteredFile, | ||
| into buffer: IORing.RegisteredBuffer, | ||
|
|
@@ -488,6 +560,14 @@ extension IORing.Request { | |
| case .cancel(let flags): | ||
| request.operation = .asyncCancel | ||
| request.cancel_flags = flags | ||
| case .pollAdd(let file, let pollEvents, let isMultiShot, let context): | ||
| request.operation = .pollAdd | ||
| request.fileDescriptor = file | ||
| request.rawValue.user_data = context | ||
| if isMultiShot { | ||
| request.rawValue.len = IORING_POLL_ADD_MULTI | ||
| } | ||
| request.rawValue.poll32_events = pollEvents.rawValue | ||
| } | ||
|
|
||
| return request | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| /* | ||
| This source file is part of the Swift System open source project | ||
|
|
||
| Copyright (c) 2020 Apple Inc. and the Swift System project authors | ||
| Licensed under Apache License v2.0 with Runtime Library Exception | ||
|
|
||
| See https://swift.org/LICENSE.txt for license information | ||
| */ | ||
|
|
||
| #if compiler(>=6.2) && $Lifetimes | ||
| #if os(Linux) | ||
| extension IORing.Request { | ||
| /// A set of I/O events that can be monitored on a file descriptor. | ||
| /// | ||
| /// `PollEvents` represents the event mask used with io_uring poll operations to specify | ||
| /// which I/O conditions to monitor on a file descriptor. These events correspond to the | ||
| /// standard Posix poll events defined in the kernel's `poll.h` header. | ||
| /// | ||
| /// Use `PollEvents` with ``IORing/Request/pollAdd(_:pollEvents:isMultiShot:context:)`` | ||
| /// to register interest in specific I/O events. The poll operation completes when any of | ||
| /// the specified events become active on the file descriptor. | ||
| /// | ||
| /// ## Usage | ||
| /// | ||
| /// ```swift | ||
| /// // Monitor a socket for incoming data | ||
| /// let request = IORing.Request.pollAdd( | ||
| /// socketFD, | ||
| /// pollEvents: .pollin, | ||
| /// isMultiShot: true | ||
| /// ) | ||
| /// ``` | ||
| public struct PollEvents: OptionSet, Hashable, Codable { | ||
| public var rawValue: UInt32 | ||
|
|
||
| @inlinable | ||
| public init(rawValue: UInt32) { | ||
Catfish-Man marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| self.rawValue = rawValue | ||
| } | ||
|
|
||
| /// An event indicating data is available for reading. | ||
| /// | ||
| /// This event becomes active when data arrives on the file descriptor and can be read | ||
| /// without blocking. For sockets, this includes when a new connection is available on | ||
| /// a listening socket. Corresponds to the Posix `POLLIN` event flag. | ||
| @inlinable | ||
| public static var pollIn: PollEvents { PollEvents(rawValue: 0x0001) } | ||
|
|
||
| /// An event indicating the file descriptor is ready for writing. | ||
| /// | ||
| /// This event becomes active when writing to the file descriptor will not block. For | ||
| /// sockets, this indicates that send buffer space is available. Corresponds to the | ||
| /// Posix `POLLOUT` event flag. | ||
| @inlinable | ||
| public static var pollOut: PollEvents { PollEvents(rawValue: 0x0004) } | ||
| } | ||
| } | ||
| #endif | ||
| #endif | ||
Uh oh!
There was an error while loading. Please reload this page.