diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index eab29e745..f4953f0d6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -72,7 +72,7 @@ For this reason, whenever you add new tests **you have to run a script** that ge
### Make sure your patch works for all supported versions of swift
-The CI will do this for you. You can use the docker-compose files included if you wish to check locally. Currently all versions of swift >= 5.6 are supported. For example usage of docker compose see the main [README](./README.md#an-alternative-using-docker-compose)
+The CI will do this for you. You can use the docker-compose files included if you wish to check locally. Currently all versions of swift >= 5.7 are supported. For example usage of docker compose see the main [README](./README.md#an-alternative-using-docker-compose)
### Make sure your code is performant
diff --git a/IntegrationTests/tests_02_syscall_wrappers/defines.sh b/IntegrationTests/tests_02_syscall_wrappers/defines.sh
index ac7793b04..c28964675 100644
--- a/IntegrationTests/tests_02_syscall_wrappers/defines.sh
+++ b/IntegrationTests/tests_02_syscall_wrappers/defines.sh
@@ -22,7 +22,7 @@ function make_package() {
fi
cat > "$tmpdir/syscallwrapper/Package.swift" <<"EOF"
-// swift-tools-version:5.6
+// swift-tools-version:5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
diff --git a/Package.swift b/Package.swift
index c23c13142..4ba1b8584 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.6
+// swift-tools-version:5.7
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
diff --git a/README.md b/README.md
index 55b77050d..565a6d078 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ It's like [Netty](https://netty.io), but written for Swift.
The SwiftNIO project is split across multiple repositories:
-Repository | NIO 2 (Swift 5.6+)
+Repository | NIO 2 (Swift 5.7+)
--- | ---
[https://github.com/apple/swift-nio][repo-nio]
SwiftNIO core | `from: "2.0.0"`
[https://github.com/apple/swift-nio-ssl][repo-nio-ssl]
TLS (SSL) support | `from: "2.0.0"`
@@ -70,7 +70,7 @@ Redis | ✅ | ❌ | [swift-server/RediStack](https://github.com/swift-server/Red
This is the current version of SwiftNIO and will be supported for the foreseeable future.
-The most recent versions of SwiftNIO support Swift 5.6 and newer. The minimum Swift version supported by SwiftNIO releases are detailed below:
+The most recent versions of SwiftNIO support Swift 5.7 and newer. The minimum Swift version supported by SwiftNIO releases are detailed below:
SwiftNIO | Minimum Swift Version
--------------------|----------------------
@@ -78,7 +78,8 @@ SwiftNIO | Minimum Swift Version
`2.30.0 ..< 2.40.0` | 5.2
`2.40.0 ..< 2.43.0` | 5.4
`2.43.0 ..< 2.51.0` | 5.5.2
-`2.51.0 ...` | 5.6
+`2.51.0 ..< 2.60.0` | 5.6
+`2.60.0 ...` | 5.7
### SwiftNIO 1
SwiftNIO 1 is considered end of life - it is strongly recommended that you move to a newer version. The Core NIO team does not actively work on this version. No new features will be added to this version but PRs which fix bugs or security vulnerabilities will be accepted until the end of May 2022.
@@ -332,7 +333,7 @@ have a few prerequisites installed on your system.
### Linux
-- Swift 5.6 or newer from [swift.org/download](https://swift.org/download/#releases). We always recommend to use the latest released version.
+- Swift 5.7 or newer from [swift.org/download](https://swift.org/download/#releases). We always recommend to use the latest released version.
- netcat (for integration tests only)
- lsof (for integration tests only)
- shasum (for integration tests only)
diff --git a/SECURITY.md b/SECURITY.md
index d1e7b82c6..4f548dcfa 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -19,8 +19,10 @@ team would create the following patch releases:
Swift 5.4 and later
* NIO 2.50. + plus next patch release to address the issue for projects that support
Swift 5.5.2 and later
-* mainline + plus next patch release to address the issue for projects that support
+* NIO 2.59. + plus next patch release to address the issue for projects that support
Swift 5.6 and later
+* mainline + plus next patch release to address the issue for projects that support
+ Swift 5.7 and later
SwiftNIO 1.x is considered end of life and will not receive any security patches.
diff --git a/Sources/NIOCore/AsyncChannel/AsyncChannelInboundStream.swift b/Sources/NIOCore/AsyncChannel/AsyncChannelInboundStream.swift
index 6826be3d9..0b5d199fd 100644
--- a/Sources/NIOCore/AsyncChannel/AsyncChannelInboundStream.swift
+++ b/Sources/NIOCore/AsyncChannel/AsyncChannelInboundStream.swift
@@ -48,20 +48,11 @@ public struct NIOAsyncChannelInboundStream: Sendable {
}
}
- #if swift(>=5.7)
@usableFromInline
enum _Backing: Sendable {
case asyncStream(AsyncThrowingStream)
case producer(Producer)
}
- #else
- // AsyncStream wasn't marked as `Sendable` in 5.6
- @usableFromInline
- enum _Backing: @unchecked Sendable {
- case asyncStream(AsyncThrowingStream)
- case producer(Producer)
- }
- #endif
/// The underlying async sequence.
@usableFromInline
diff --git a/Sources/NIOCore/AsyncChannel/AsyncChannelOutboundWriter.swift b/Sources/NIOCore/AsyncChannel/AsyncChannelOutboundWriter.swift
index 13934d5ec..4fda58f12 100644
--- a/Sources/NIOCore/AsyncChannel/AsyncChannelOutboundWriter.swift
+++ b/Sources/NIOCore/AsyncChannel/AsyncChannelOutboundWriter.swift
@@ -163,11 +163,5 @@ public struct NIOAsyncChannelOutboundWriter: Sendable {
}
}
-#if swift(>=5.7)
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension NIOAsyncChannelOutboundWriter.TestSink: Sendable {}
-#else
-// AsyncStream wasn't marked as `Sendable` in 5.6
-@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
-extension NIOAsyncChannelOutboundWriter.TestSink: @unchecked Sendable {}
-#endif
diff --git a/Sources/NIOCore/ChannelHandlers.swift b/Sources/NIOCore/ChannelHandlers.swift
index 89dbc594d..18a9318f4 100644
--- a/Sources/NIOCore/ChannelHandlers.swift
+++ b/Sources/NIOCore/ChannelHandlers.swift
@@ -105,10 +105,8 @@ public final class AcceptBackoffHandler: ChannelDuplexHandler, RemovableChannelH
}
}
-#if swift(>=5.7)
@available(*, unavailable)
extension AcceptBackoffHandler: Sendable {}
-#endif
/**
ChannelHandler implementation which enforces back-pressure by stopping to read from the remote peer when it cannot write back fast enough.
@@ -157,10 +155,8 @@ public final class BackPressureHandler: ChannelDuplexHandler, RemovableChannelHa
}
}
-#if swift(>=5.7)
@available(*, unavailable)
extension BackPressureHandler: Sendable {}
-#endif
/// Triggers an IdleStateEvent when a Channel has not performed read, write, or both operation for a while.
public final class IdleStateHandler: ChannelDuplexHandler, RemovableChannelHandler {
@@ -347,7 +343,5 @@ public final class IdleStateHandler: ChannelDuplexHandler, RemovableChannelHandl
}
}
-#if swift(>=5.7)
@available(*, unavailable)
extension IdleStateHandler: Sendable {}
-#endif
diff --git a/Sources/NIOCore/ChannelPipeline.swift b/Sources/NIOCore/ChannelPipeline.swift
index d9d2c72ec..246d86c0f 100644
--- a/Sources/NIOCore/ChannelPipeline.swift
+++ b/Sources/NIOCore/ChannelPipeline.swift
@@ -946,9 +946,7 @@ public final class ChannelPipeline: ChannelInvoker {
}
}
-#if swift(>=5.7)
extension ChannelPipeline: @unchecked Sendable {}
-#endif
extension ChannelPipeline {
/// Adds the provided channel handlers to the pipeline in the order given, taking account
@@ -1274,10 +1272,8 @@ extension ChannelPipeline {
}
}
-#if swift(>=5.7)
@available(*, unavailable)
extension ChannelPipeline.SynchronousOperations: Sendable {}
-#endif
extension ChannelPipeline {
/// A `Position` within the `ChannelPipeline` used to insert handlers into the `ChannelPipeline`.
@@ -1296,10 +1292,8 @@ extension ChannelPipeline {
}
}
-#if swift(>=5.7)
@available(*, unavailable)
extension ChannelPipeline.Position: Sendable {}
-#endif
/// Special `ChannelHandler` that forwards all events to the `Channel.Unsafe` implementation.
/* private but tests */ final class HeadChannelHandler: _ChannelOutboundHandler {
@@ -1853,10 +1847,8 @@ public final class ChannelHandlerContext: ChannelInvoker {
}
}
-#if swift(>=5.7)
@available(*, unavailable)
extension ChannelHandlerContext: Sendable {}
-#endif
extension ChannelHandlerContext {
/// A `RemovalToken` is handed to a `RemovableChannelHandler` when its `removeHandler` function is invoked. A
diff --git a/Sources/NIOCore/Codec.swift b/Sources/NIOCore/Codec.swift
index 5d79ab39b..a46beac87 100644
--- a/Sources/NIOCore/Codec.swift
+++ b/Sources/NIOCore/Codec.swift
@@ -485,10 +485,8 @@ public final class ByteToMessageHandler {
}
}
-#if swift(>=5.7)
@available(*, unavailable)
extension ByteToMessageHandler: Sendable {}
-#endif
// MARK: ByteToMessageHandler: Test Helpers
extension ByteToMessageHandler {
@@ -776,10 +774,8 @@ public final class MessageToByteHandler: ChannelO
}
}
-#if swift(>=5.7)
@available(*, unavailable)
extension MessageToByteHandler: Sendable {}
-#endif
extension MessageToByteHandler {
public func handlerAdded(context: ChannelHandlerContext) {
diff --git a/Sources/NIOCore/EventLoop.swift b/Sources/NIOCore/EventLoop.swift
index 6675f118f..fe65e3c55 100644
--- a/Sources/NIOCore/EventLoop.swift
+++ b/Sources/NIOCore/EventLoop.swift
@@ -23,28 +23,16 @@ import CNIOLinux
/// A `Scheduled` allows the user to either `cancel()` the execution of the scheduled task (if possible) or obtain a reference to the `EventLoopFuture` that
/// will be notified once the execution is complete.
public struct Scheduled {
- #if swift(>=5.7)
@usableFromInline typealias CancelationCallback = @Sendable () -> Void
- #else
- @usableFromInline typealias CancelationCallback = () -> Void
- #endif
/* private but usableFromInline */ @usableFromInline let _promise: EventLoopPromise
/* private but usableFromInline */ @usableFromInline let _cancellationTask: CancelationCallback
- #if swift(>=5.7)
@inlinable
@preconcurrency
public init(promise: EventLoopPromise, cancellationTask: @escaping @Sendable () -> Void) {
self._promise = promise
self._cancellationTask = cancellationTask
}
- #else
- @inlinable
- public init(promise: EventLoopPromise, cancellationTask: @escaping () -> Void) {
- self._promise = promise
- self._cancellationTask = cancellationTask
- }
- #endif
/// Try to cancel the execution of the scheduled task.
///
@@ -63,19 +51,13 @@ public struct Scheduled {
}
}
-#if swift(>=5.7)
extension Scheduled: Sendable where T: Sendable {}
-#endif
/// Returned once a task was scheduled to be repeatedly executed on the `EventLoop`.
///
/// A `RepeatedTask` allows the user to `cancel()` the repeated scheduling of further tasks.
public final class RepeatedTask {
- #if swift(>=5.7)
typealias RepeatedTaskCallback = @Sendable (RepeatedTask) -> EventLoopFuture
- #else
- typealias RepeatedTaskCallback = (RepeatedTask) -> EventLoopFuture
- #endif
private let delay: TimeAmount
private let eventLoop: EventLoop
private let cancellationPromise: EventLoopPromise?
@@ -196,9 +178,7 @@ public final class RepeatedTask {
}
}
-#if swift(>=5.7)
extension RepeatedTask: @unchecked Sendable {}
-#endif
/// An iterator over the `EventLoop`s forming an `EventLoopGroup`.
///
@@ -226,9 +206,7 @@ public struct EventLoopIterator: Sequence, IteratorProtocol {
}
}
-#if swift(>=5.7)
extension EventLoopIterator: Sendable {}
-#endif
/// An EventLoop processes IO / tasks in an endless loop for `Channel`s until it's closed.
///
@@ -270,16 +248,10 @@ public protocol EventLoop: EventLoopGroup {
/// If it is necessary for correctness to confirm that you're on an event loop, prefer ``preconditionInEventLoop(file:line:)-7ukrq``.
var inEventLoop: Bool { get }
- #if swift(>=5.7)
/// Submit a given task to be executed by the `EventLoop`
@preconcurrency
func execute(_ task: @escaping @Sendable () -> Void)
- #else
- /// Submit a given task to be executed by the `EventLoop`
- func execute(_ task: @escaping () -> Void)
- #endif
-
- #if swift(>=5.7)
+
/// Submit a given task to be executed by the `EventLoop`. Once the execution is complete the returned `EventLoopFuture` is notified.
///
/// - parameters:
@@ -287,16 +259,6 @@ public protocol EventLoop: EventLoopGroup {
/// - returns: `EventLoopFuture` that is notified once the task was executed.
@preconcurrency
func submit(_ task: @escaping @Sendable () throws -> T) -> EventLoopFuture
- #else
- /// Submit a given task to be executed by the `EventLoop`. Once the execution is complete the returned `EventLoopFuture` is notified.
- ///
- /// - parameters:
- /// - task: The closure that will be submitted to the `EventLoop` for execution.
- /// - returns: `EventLoopFuture` that is notified once the task was executed.
- func submit(_ task: @escaping () throws -> T) -> EventLoopFuture
- #endif
-
- #if swift(>=5.7)
/// Schedule a `task` that is executed by this `EventLoop` at the given time.
///
@@ -309,20 +271,6 @@ public protocol EventLoop: EventLoopGroup {
@discardableResult
@preconcurrency
func scheduleTask(deadline: NIODeadline, _ task: @escaping @Sendable () throws -> T) -> Scheduled
- #else
- /// Schedule a `task` that is executed by this `EventLoop` at the given time.
- ///
- /// - parameters:
- /// - task: The synchronous task to run. As with everything that runs on the `EventLoop`, it must not block.
- /// - returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait
- /// on the completion of the task.
- ///
- /// - note: You can only cancel a task before it has started executing.
- @discardableResult
- func scheduleTask(deadline: NIODeadline, _ task: @escaping () throws -> T) -> Scheduled
- #endif
-
- #if swift(>=5.7)
/// Schedule a `task` that is executed by this `EventLoop` after the given amount of time.
///
@@ -336,19 +284,6 @@ public protocol EventLoop: EventLoopGroup {
@discardableResult
@preconcurrency
func scheduleTask(in: TimeAmount, _ task: @escaping @Sendable () throws -> T) -> Scheduled
- #else
- /// Schedule a `task` that is executed by this `EventLoop` after the given amount of time.
- ///
- /// - parameters:
- /// - task: The synchronous task to run. As with everything that runs on the `EventLoop`, it must not block.
- /// - returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait
- /// on the completion of the task.
- ///
- /// - note: You can only cancel a task before it has started executing.
- /// - note: The `in` value is clamped to a maximum when running on a Darwin-kernel.
- @discardableResult
- func scheduleTask(in: TimeAmount, _ task: @escaping () throws -> T) -> Scheduled
- #endif
/// Asserts that the current thread is the one tied to this `EventLoop`.
/// Otherwise, the process will be abnormally terminated as per the semantics of `preconditionFailure(_:file:line:)`.
@@ -725,7 +660,6 @@ extension NIODeadline {
}
extension EventLoop {
- #if swift(>=5.7)
/// Submit `task` to be run on this `EventLoop`.
///
/// The returned `EventLoopFuture` will be completed when `task` has finished running. It will be succeeded with
@@ -740,22 +674,7 @@ extension EventLoop {
_submit(task)
}
@usableFromInline typealias SubmitCallback = @Sendable () throws -> T
- #else
- /// Submit `task` to be run on this `EventLoop`.
- ///
- /// The returned `EventLoopFuture` will be completed when `task` has finished running. It will be succeeded with
- /// `task`'s return value or failed if the execution of `task` threw an error.
- ///
- /// - parameters:
- /// - task: The synchronous task to run. As everything that runs on the `EventLoop`, it must not block.
- /// - returns: An `EventLoopFuture` containing the result of `task`'s execution.
- @inlinable
- public func submit(_ task: @escaping () throws -> T) -> EventLoopFuture {
- _submit(task)
- }
- @usableFromInline typealias SubmitCallback = () throws -> T
- #endif
-
+
@inlinable
func _submit(_ task: @escaping SubmitCallback) -> EventLoopFuture {
let promise: EventLoopPromise = makePromise(file: #fileID, line: #line)
@@ -771,7 +690,6 @@ extension EventLoop {
return promise.futureResult
}
- #if swift(>=5.7)
/// Submit `task` to be run on this `EventLoop`.
///
/// The returned `EventLoopFuture` will be completed when `task` has finished running. It will be identical to
@@ -786,28 +704,12 @@ extension EventLoop {
self._flatSubmit(task)
}
@usableFromInline typealias FlatSubmitCallback = @Sendable () -> EventLoopFuture
- #else
- /// Submit `task` to be run on this `EventLoop`.
- ///
- /// The returned `EventLoopFuture` will be completed when `task` has finished running. It will be identical to
- /// the `EventLoopFuture` returned by `task`.
- ///
- /// - parameters:
- /// - task: The asynchronous task to run. As with everything that runs on the `EventLoop`, it must not block.
- /// - returns: An `EventLoopFuture` identical to the `EventLoopFuture` returned from `task`.
- @inlinable
- public func flatSubmit(_ task: @escaping () -> EventLoopFuture) -> EventLoopFuture {
- self._flatSubmit(task)
- }
- @usableFromInline typealias FlatSubmitCallback = () -> EventLoopFuture
- #endif
-
+
@inlinable
func _flatSubmit(_ task: @escaping FlatSubmitCallback) -> EventLoopFuture {
self.submit(task).flatMap { $0 }
}
-
- #if swift(>=5.7)
+
/// Schedule a `task` that is executed by this `EventLoop` at the given time.
///
/// - parameters:
@@ -828,28 +730,7 @@ extension EventLoop {
self._flatScheduleTask(deadline: deadline, file: file, line: line, task)
}
@usableFromInline typealias FlatScheduleTaskDeadlineCallback = () throws -> EventLoopFuture
- #else
- /// Schedule a `task` that is executed by this `EventLoop` at the given time.
- ///
- /// - parameters:
- /// - task: The asynchronous task to run. As with everything that runs on the `EventLoop`, it must not block.
- /// - returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait
- /// on the full execution of the task, including its returned `EventLoopFuture`.
- ///
- /// - note: You can only cancel a task before it has started executing.
- @discardableResult
- @inlinable
- public func flatScheduleTask(
- deadline: NIODeadline,
- file: StaticString = #fileID,
- line: UInt = #line,
- _ task: @escaping () throws -> EventLoopFuture
- ) -> Scheduled {
- self._flatScheduleTask(deadline: deadline, file: file, line: line, task)
- }
- @usableFromInline typealias FlatScheduleTaskDeadlineCallback = () throws -> EventLoopFuture
- #endif
-
+
@discardableResult
@inlinable
func _flatScheduleTask(
@@ -865,7 +746,6 @@ extension EventLoop {
return .init(promise: promise, cancellationTask: { scheduled.cancel() })
}
- #if swift(>=5.7)
/// Schedule a `task` that is executed by this `EventLoop` after the given amount of time.
///
/// - parameters:
@@ -886,28 +766,7 @@ extension EventLoop {
self._flatScheduleTask(in: delay, file: file, line: line, task)
}
@usableFromInline typealias FlatScheduleTaskDelayCallback = @Sendable () throws -> EventLoopFuture
- #else
- /// Schedule a `task` that is executed by this `EventLoop` after the given amount of time.
- ///
- /// - parameters:
- /// - task: The asynchronous task to run. As everything that runs on the `EventLoop`, it must not block.
- /// - returns: A `Scheduled` object which may be used to cancel the task if it has not yet run, or to wait
- /// on the full execution of the task, including its returned `EventLoopFuture`.
- ///
- /// - note: You can only cancel a task before it has started executing.
- @discardableResult
- @inlinable
- public func flatScheduleTask(
- in delay: TimeAmount,
- file: StaticString = #fileID,
- line: UInt = #line,
- _ task: @escaping () throws -> EventLoopFuture
- ) -> Scheduled {
- self._flatScheduleTask(in: delay, file: file, line: line, task)
- }
- @usableFromInline typealias FlatScheduleTaskDelayCallback = () throws -> EventLoopFuture
- #endif
-
+
@inlinable
func _flatScheduleTask(
in delay: TimeAmount,
@@ -998,7 +857,6 @@ extension EventLoop {
// Do nothing
}
- #if swift(>=5.7)
/// Schedule a repeated task to be executed by the `EventLoop` with a fixed delay between the end and start of each
/// task.
@@ -1020,28 +878,7 @@ extension EventLoop {
self._scheduleRepeatedTask(initialDelay: initialDelay, delay: delay, notifying: promise, task)
}
typealias ScheduleRepeatedTaskCallback = @Sendable (RepeatedTask) throws -> Void
- #else
- /// Schedule a repeated task to be executed by the `EventLoop` with a fixed delay between the end and start of each
- /// task.
- ///
- /// - parameters:
- /// - initialDelay: The delay after which the first task is executed.
- /// - delay: The delay between the end of one task and the start of the next.
- /// - promise: If non-nil, a promise to fulfill when the task is cancelled and all execution is complete.
- /// - task: The closure that will be executed.
- /// - return: `RepeatedTask`
- @discardableResult
- public func scheduleRepeatedTask(
- initialDelay: TimeAmount,
- delay: TimeAmount,
- notifying promise: EventLoopPromise? = nil,
- _ task: @escaping (RepeatedTask) throws -> Void
- ) -> RepeatedTask {
- self._scheduleRepeatedTask(initialDelay: initialDelay, delay: delay, notifying: promise, task)
- }
- typealias ScheduleRepeatedTaskCallback = (RepeatedTask) throws -> Void
- #endif
-
+
func _scheduleRepeatedTask(
initialDelay: TimeAmount,
delay: TimeAmount,
@@ -1059,7 +896,6 @@ extension EventLoop {
return self.scheduleRepeatedAsyncTask(initialDelay: initialDelay, delay: delay, notifying: promise, futureTask)
}
- #if swift(>=5.7)
/// Schedule a repeated asynchronous task to be executed by the `EventLoop` with a fixed delay between the end and
/// start of each task.
///
@@ -1087,35 +923,7 @@ extension EventLoop {
self._scheduleRepeatedAsyncTask(initialDelay: initialDelay, delay: delay, notifying: promise, task)
}
typealias ScheduleRepeatedAsyncTaskCallback = @Sendable (RepeatedTask) -> EventLoopFuture
- #else
- /// Schedule a repeated asynchronous task to be executed by the `EventLoop` with a fixed delay between the end and
- /// start of each task.
- ///
- /// - note: The delay is measured from the completion of one run's returned future to the start of the execution of
- /// the next run. For example: If you schedule a task once per second but your task takes two seconds to
- /// complete, the time interval between two subsequent runs will actually be three seconds (2s run time plus
- /// the 1s delay.)
- ///
- /// - parameters:
- /// - initialDelay: The delay after which the first task is executed.
- /// - delay: The delay between the end of one task and the start of the next.
- /// - promise: If non-nil, a promise to fulfill when the task is cancelled and all execution is complete.
- /// - task: The closure that will be executed. Task will keep repeating regardless of whether the future
- /// gets fulfilled with success or error.
- ///
- /// - return: `RepeatedTask`
- @discardableResult
- public func scheduleRepeatedAsyncTask(
- initialDelay: TimeAmount,
- delay: TimeAmount,
- notifying promise: EventLoopPromise? = nil,
- _ task: @escaping (RepeatedTask) -> EventLoopFuture
- ) -> RepeatedTask {
- self._scheduleRepeatedAsyncTask(initialDelay: initialDelay, delay: delay, notifying: promise, task)
- }
- typealias ScheduleRepeatedAsyncTaskCallback = (RepeatedTask) -> EventLoopFuture
- #endif
-
+
func _scheduleRepeatedAsyncTask(
initialDelay: TimeAmount,
delay: TimeAmount,
@@ -1210,20 +1018,12 @@ public protocol EventLoopGroup: AnyObject, _NIOPreconcurrencySendable {
/// future or kick off some operation, use `any()`.
func any() -> EventLoop
- #if swift(>=5.7)
/// Shuts down the eventloop gracefully. This function is clearly an outlier in that it uses a completion
/// callback instead of an EventLoopFuture. The reason for that is that NIO's EventLoopFutures will call back on an event loop.
/// The virtue of this function is to shut the event loop down. To work around that we call back on a DispatchQueue
/// instead.
@preconcurrency func shutdownGracefully(queue: DispatchQueue, _ callback: @Sendable @escaping (Error?) -> Void)
- #else
- /// Shuts down the eventloop gracefully. This function is clearly an outlier in that it uses a completion
- /// callback instead of an EventLoopFuture. The reason for that is that NIO's EventLoopFutures will call back on an event loop.
- /// The virtue of this function is to shut the event loop down. To work around that we call back on a DispatchQueue
- /// instead.
- func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping (Error?) -> Void)
- #endif
-
+
/// Returns an `EventLoopIterator` over the `EventLoop`s in this `EventLoopGroup`.
///
/// - returns: `EventLoopIterator`
@@ -1245,27 +1045,14 @@ extension EventLoopGroup {
}
extension EventLoopGroup {
- #if swift(>=5.7)
@preconcurrency public func shutdownGracefully(_ callback: @escaping @Sendable (Error?) -> Void) {
self.shutdownGracefully(queue: .global(), callback)
}
- #else
- public func shutdownGracefully(_ callback: @escaping (Error?) -> Void) {
- self.shutdownGracefully(queue: .global(), callback)
- }
- #endif
-
- #if swift(>=5.7)
@available(*, noasync, message: "this can end up blocking the calling thread", renamed: "shutdownGracefully()")
public func syncShutdownGracefully() throws {
try self._syncShutdownGracefully()
}
- #else
- public func syncShutdownGracefully() throws {
- try self._syncShutdownGracefully()
- }
- #endif
private func _syncShutdownGracefully() throws {
self._preconditionSafeToSyncShutdown(file: #fileID, line: #line)
@@ -1306,9 +1093,7 @@ public enum NIOEventLoopGroupProvider {
case createNew
}
-#if swift(>=5.7)
extension NIOEventLoopGroupProvider: Sendable {}
-#endif
/// Different `Error`s that are specific to `EventLoop` operations / implementations.
public enum EventLoopError: Error {
diff --git a/Sources/NIOCore/EventLoopFuture.swift b/Sources/NIOCore/EventLoopFuture.swift
index 6c79a08ef..185e00fec 100644
--- a/Sources/NIOCore/EventLoopFuture.swift
+++ b/Sources/NIOCore/EventLoopFuture.swift
@@ -24,13 +24,8 @@ import Dispatch
/// This eliminates recursion when processing `flatMap()` chains.
@usableFromInline
internal struct CallbackList {
- #if swift(>=5.7)
@usableFromInline
internal typealias Element = @Sendable () -> CallbackList
- #else
- @usableFromInline
- internal typealias Element = () -> CallbackList
- #endif
@usableFromInline
internal var firstCallback: Optional
@usableFromInline
@@ -196,7 +191,7 @@ public struct EventLoopPromise {
public func fail(_ error: Error) {
self._resolve(value: .failure(error))
}
-
+
/// Complete the promise with the passed in `EventLoopFuture`.
///
/// This method is equivalent to invoking `future.cascade(to: promise)`,
@@ -259,7 +254,6 @@ public struct EventLoopPromise {
}
}
-
/// Holder for a result that will be provided later.
///
/// Functions that promise to do work asynchronously can return an `EventLoopFuture`.
@@ -447,7 +441,6 @@ extension EventLoopFuture: Equatable {
// 'flatMap' and 'map' implementations. This is really the key of the entire system.
extension EventLoopFuture {
- #if swift(>=5.7)
/// When the current `EventLoopFuture` is fulfilled, run the provided callback,
/// which will provide a new `EventLoopFuture`.
///
@@ -481,41 +474,7 @@ extension EventLoopFuture {
self._flatMap(callback)
}
@usableFromInline typealias FlatMapCallback = @Sendable (Value) -> EventLoopFuture
- #else
- /// When the current `EventLoopFuture` is fulfilled, run the provided callback,
- /// which will provide a new `EventLoopFuture`.
- ///
- /// This allows you to dynamically dispatch new asynchronous tasks as phases in a
- /// longer series of processing steps. Note that you can use the results of the
- /// current `EventLoopFuture` when determining how to dispatch the next operation.
- ///
- /// This works well when you have APIs that already know how to return `EventLoopFuture`s.
- /// You can do something with the result of one and just return the next future:
- ///
- /// ```
- /// let d1 = networkRequest(args).future()
- /// let d2 = d1.flatMap { t -> EventLoopFuture in
- /// . . . something with t . . .
- /// return netWorkRequest(args)
- /// }
- /// d2.whenSuccess { u in
- /// NSLog("Result of second request: \(u)")
- /// }
- /// ```
- ///
- /// Note: In a sense, the `EventLoopFuture` is returned before it's created.
- ///
- /// - parameters:
- /// - callback: Function that will receive the value of this `EventLoopFuture` and return
- /// a new `EventLoopFuture`.
- /// - returns: A future that will receive the eventual value.
- @inlinable
- public func flatMap(_ callback: @escaping (Value) -> EventLoopFuture) -> EventLoopFuture {
- self._flatMap(callback)
- }
- @usableFromInline typealias FlatMapCallback = (Value) -> EventLoopFuture
- #endif
-
+
@inlinable
func _flatMap(_ callback: @escaping FlatMapCallback) -> EventLoopFuture {
let next = EventLoopPromise.makeUnleakablePromise(eventLoop: self.eventLoop)
@@ -537,8 +496,7 @@ extension EventLoopFuture {
}
return next.futureResult
}
-
- #if swift(>=5.7)
+
/// When the current `EventLoopFuture` is fulfilled, run the provided callback, which
/// performs a synchronous computation and returns a new value of type `NewValue`. The provided
/// callback may optionally `throw`.
@@ -559,28 +517,7 @@ extension EventLoopFuture {
self._flatMapThrowing(callback)
}
@usableFromInline typealias FlatMapThrowingCallback = @Sendable (Value) throws -> NewValue
- #else
- /// When the current `EventLoopFuture` is fulfilled, run the provided callback, which
- /// performs a synchronous computation and returns a new value of type `NewValue`. The provided
- /// callback may optionally `throw`.
- ///
- /// Operations performed in `flatMapThrowing` should not block, or they will block the entire
- /// event loop. `flatMapThrowing` is intended for use when you have a data-driven function that
- /// performs a simple data transformation that can potentially error.
- ///
- /// If your callback function throws, the returned `EventLoopFuture` will error.
- ///
- /// - parameters:
- /// - callback: Function that will receive the value of this `EventLoopFuture` and return
- /// a new value lifted into a new `EventLoopFuture`.
- /// - returns: A future that will receive the eventual value.
- @inlinable
- public func flatMapThrowing(_ callback: @escaping (Value) throws -> NewValue) -> EventLoopFuture {
- self._flatMapThrowing(callback)
- }
- @usableFromInline typealias FlatMapThrowingCallback = (Value) throws -> NewValue
- #endif
-
+
@inlinable
func _flatMapThrowing(_ callback: @escaping FlatMapThrowingCallback) -> EventLoopFuture {
let next = EventLoopPromise.makeUnleakablePromise(eventLoop: self.eventLoop)
@@ -599,8 +536,7 @@ extension EventLoopFuture {
}
return next.futureResult
}
-
- #if swift(>=5.7)
+
/// When the current `EventLoopFuture` is in an error state, run the provided callback, which
/// may recover from the error and returns a new value of type `Value`. The provided callback may optionally `throw`,
/// in which case the `EventLoopFuture` will be in a failed state with the new thrown error.
@@ -621,28 +557,7 @@ extension EventLoopFuture {
self._flatMapErrorThrowing(callback)
}
@usableFromInline typealias FlatMapErrorThrowingCallback = @Sendable (Error) throws -> Value
- #else
- /// When the current `EventLoopFuture` is in an error state, run the provided callback, which
- /// may recover from the error and returns a new value of type `Value`. The provided callback may optionally `throw`,
- /// in which case the `EventLoopFuture` will be in a failed state with the new thrown error.
- ///
- /// Operations performed in `flatMapErrorThrowing` should not block, or they will block the entire
- /// event loop. `flatMapErrorThrowing` is intended for use when you have the ability to synchronously
- /// recover from errors.
- ///
- /// If your callback function throws, the returned `EventLoopFuture` will error.
- ///
- /// - parameters:
- /// - callback: Function that will receive the error value of this `EventLoopFuture` and return
- /// a new value lifted into a new `EventLoopFuture`.
- /// - returns: A future that will receive the eventual value or a rethrown error.
- @inlinable
- public func flatMapErrorThrowing(_ callback: @escaping (Error) throws -> Value) -> EventLoopFuture {
- self._flatMapErrorThrowing(callback)
- }
- @usableFromInline typealias FlatMapErrorThrowingCallback = (Error) throws -> Value
- #endif
-
+
@inlinable
func _flatMapErrorThrowing(_ callback: @escaping FlatMapErrorThrowingCallback) -> EventLoopFuture {
let next = EventLoopPromise.makeUnleakablePromise(eventLoop: self.eventLoop)
@@ -662,7 +577,6 @@ extension EventLoopFuture {
return next.futureResult
}
- #if swift(>=5.7)
/// When the current `EventLoopFuture` is fulfilled, run the provided callback, which
/// performs a synchronous computation and returns a new value of type `NewValue`.
///
@@ -695,48 +609,11 @@ extension EventLoopFuture {
self._map(callback)
}
@usableFromInline typealias MapCallback = @Sendable (Value) -> (NewValue)
- #else
- /// When the current `EventLoopFuture` is fulfilled, run the provided callback, which
- /// performs a synchronous computation and returns a new value of type `NewValue`.
- ///
- /// Operations performed in `map` should not block, or they will block the entire event
- /// loop. `map` is intended for use when you have a data-driven function that performs
- /// a simple data transformation that cannot error.
- ///
- /// If you have a data-driven function that can throw, you should use `flatMapThrowing`
- /// instead.
- ///
- /// ```
- /// let future1 = eventually()
- /// let future2 = future1.map { T -> U in
- /// ... stuff ...
- /// return u
- /// }
- /// let future3 = future2.map { U -> V in
- /// ... stuff ...
- /// return v
- /// }
- /// ```
- ///
- /// - parameters:
- /// - callback: Function that will receive the value of this `EventLoopFuture` and return
- /// a new value lifted into a new `EventLoopFuture`.
- /// - returns: A future that will receive the eventual value.
- @inlinable
- public func map(_ callback: @escaping (Value) -> (NewValue)) -> EventLoopFuture {
- self._map(callback)
- }
- @usableFromInline typealias MapCallback = (Value) -> (NewValue)
- #endif
-
+
@inlinable
func _map(_ callback: @escaping MapCallback) -> EventLoopFuture {
if NewValue.self == Value.self && NewValue.self == Void.self {
- #if swift(>=5.7)
self.whenSuccess(callback as! @Sendable (Value) -> Void)
- #else
- self.whenSuccess(callback as! (Value) -> Void)
- #endif
return self as! EventLoopFuture
} else {
let next = EventLoopPromise.makeUnleakablePromise(eventLoop: self.eventLoop)
@@ -747,7 +624,6 @@ extension EventLoopFuture {
}
}
- #if swift(>=5.7)
/// When the current `EventLoopFuture` is in an error state, run the provided callback, which
/// may recover from the error by returning an `EventLoopFuture`. The callback is intended to potentially
/// recover from the error by returning a new `EventLoopFuture` that will eventually contain the recovered
@@ -765,25 +641,7 @@ extension EventLoopFuture {
self._flatMapError(callback)
}
@usableFromInline typealias FlatMapErrorCallback = @Sendable (Error) -> EventLoopFuture
- #else
- /// When the current `EventLoopFuture` is in an error state, run the provided callback, which
- /// may recover from the error by returning an `EventLoopFuture`. The callback is intended to potentially
- /// recover from the error by returning a new `EventLoopFuture` that will eventually contain the recovered
- /// result.
- ///
- /// If the callback cannot recover it should return a failed `EventLoopFuture`.
- ///
- /// - parameters:
- /// - callback: Function that will receive the error value of this `EventLoopFuture` and return
- /// a new value lifted into a new `EventLoopFuture`.
- /// - returns: A future that will receive the recovered value.
- @inlinable
- public func flatMapError(_ callback: @escaping (Error) -> EventLoopFuture) -> EventLoopFuture {
- self._flatMapError(callback)
- }
- @usableFromInline typealias FlatMapErrorCallback = (Error) -> EventLoopFuture
- #endif
-
+
@inlinable
func _flatMapError(_ callback: @escaping FlatMapErrorCallback) -> EventLoopFuture {
let next = EventLoopPromise.makeUnleakablePromise(eventLoop: self.eventLoop)
@@ -806,7 +664,6 @@ extension EventLoopFuture {
return next.futureResult
}
- #if swift(>=5.7)
/// When the current `EventLoopFuture` is fulfilled, run the provided callback, which
/// performs a synchronous computation and returns either a new value (of type `NewValue`) or
/// an error depending on the `Result` returned by the closure.
@@ -826,27 +683,7 @@ extension EventLoopFuture {
self._flatMapResult(body)
}
@usableFromInline typealias FlatMapResultCallback = @Sendable (Value) -> Result
- #else
- /// When the current `EventLoopFuture` is fulfilled, run the provided callback, which
- /// performs a synchronous computation and returns either a new value (of type `NewValue`) or
- /// an error depending on the `Result` returned by the closure.
- ///
- /// Operations performed in `flatMapResult` should not block, or they will block the entire
- /// event loop. `flatMapResult` is intended for use when you have a data-driven function that
- /// performs a simple data transformation that can potentially error.
- ///
- ///
- /// - parameters:
- /// - body: Function that will receive the value of this `EventLoopFuture` and return
- /// a new value or error lifted into a new `EventLoopFuture`.
- /// - returns: A future that will receive the eventual value.
- @inlinable
- public func flatMapResult(_ body: @escaping (Value) -> Result) -> EventLoopFuture {
- self._flatMapResult(body)
- }
- @usableFromInline typealias FlatMapResultCallback = (Value) -> Result
- #endif
-
+
@inlinable
func _flatMapResult(_ body: @escaping FlatMapResultCallback) -> EventLoopFuture {
let next = EventLoopPromise.makeUnleakablePromise(eventLoop: self.eventLoop)
@@ -866,7 +703,6 @@ extension EventLoopFuture {
return next.futureResult
}
- #if swift(>=5.7)
/// When the current `EventLoopFuture` is in an error state, run the provided callback, which
/// can recover from the error and return a new value of type `Value`. The provided callback may not `throw`,
/// so this function should be used when the error is always recoverable.
@@ -885,26 +721,7 @@ extension EventLoopFuture {
self._recover(callback)
}
@usableFromInline typealias RecoverCallback = @Sendable (Error) -> Value
- #else
- /// When the current `EventLoopFuture` is in an error state, run the provided callback, which
- /// can recover from the error and return a new value of type `Value`. The provided callback may not `throw`,
- /// so this function should be used when the error is always recoverable.
- ///
- /// Operations performed in `recover` should not block, or they will block the entire
- /// event loop. `recover` is intended for use when you have the ability to synchronously
- /// recover from errors.
- ///
- /// - parameters:
- /// - callback: Function that will receive the error value of this `EventLoopFuture` and return
- /// a new value lifted into a new `EventLoopFuture`.
- /// - returns: A future that will receive the recovered value.
- @inlinable
- public func recover(_ callback: @escaping (Error) -> Value) -> EventLoopFuture {
- self._recover(callback)
- }
- @usableFromInline typealias RecoverCallback = (Error) -> Value
- #endif
-
+
@inlinable
func _recover(_ callback: @escaping RecoverCallback) -> EventLoopFuture {
let next = EventLoopPromise.makeUnleakablePromise(eventLoop: self.eventLoop)
@@ -919,11 +736,7 @@ extension EventLoopFuture {
return next.futureResult
}
- #if swift(>=5.7)
@usableFromInline typealias AddCallbackCallback = @Sendable () -> CallbackList
- #else
- @usableFromInline typealias AddCallbackCallback = () -> CallbackList
- #endif
/// Add a callback. If there's already a value, invoke it and return the resulting list of new callback functions.
@inlinable
internal func _addCallback(_ callback: @escaping AddCallbackCallback) -> CallbackList {
@@ -934,8 +747,7 @@ extension EventLoopFuture {
}
return callback()
}
-
- #if swift(>=5.7)
+
/// Add a callback. If there's already a value, run as much of the chain as we can.
@inlinable
@preconcurrency // TODO: We want to remove @preconcurrency but it results in more allocations in 1000_udpconnections
@@ -943,15 +755,7 @@ extension EventLoopFuture {
self._internalWhenComplete(callback)
}
@usableFromInline typealias InternalWhenCompleteCallback = @Sendable () -> CallbackList
- #else
- /// Add a callback. If there's already a value, run as much of the chain as we can.
- @inlinable
- internal func _whenComplete(_ callback: @escaping () -> CallbackList) {
- self._internalWhenComplete(callback)
- }
- @usableFromInline typealias InternalWhenCompleteCallback = () -> CallbackList
- #endif
-
+
/// Add a callback. If there's already a value, run as much of the chain as we can.
@inlinable
internal func _internalWhenComplete(_ callback: @escaping InternalWhenCompleteCallback) {
@@ -964,7 +768,6 @@ extension EventLoopFuture {
}
}
- #if swift(>=5.7)
/// Adds an observer callback to this `EventLoopFuture` that is called when the
/// `EventLoopFuture` has a success result.
///
@@ -981,24 +784,7 @@ extension EventLoopFuture {
self._whenSuccess(callback)
}
@usableFromInline typealias WhenSuccessCallback = @Sendable (Value) -> Void
- #else
- /// Adds an observer callback to this `EventLoopFuture` that is called when the
- /// `EventLoopFuture` has a success result.
- ///
- /// An observer callback cannot return a value, meaning that this function cannot be chained
- /// from. If you are attempting to create a computation pipeline, consider `map` or `flatMap`.
- /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`
- /// in the body of this function, consider using `cascade` instead.
- ///
- /// - parameters:
- /// - callback: The callback that is called with the successful result of the `EventLoopFuture`.
- @inlinable
- public func whenSuccess(_ callback: @escaping (Value) -> Void) {
- self._whenSuccess(callback)
- }
- @usableFromInline typealias WhenSuccessCallback = (Value) -> Void
- #endif
-
+
@inlinable
func _whenSuccess(_ callback: @escaping WhenSuccessCallback) {
self._whenComplete {
@@ -1008,8 +794,7 @@ extension EventLoopFuture {
return CallbackList()
}
}
-
- #if swift(>=5.7)
+
/// Adds an observer callback to this `EventLoopFuture` that is called when the
/// `EventLoopFuture` has a failure result.
///
@@ -1026,24 +811,7 @@ extension EventLoopFuture {
self._whenFailure(callback)
}
@usableFromInline typealias WhenFailureCallback = @Sendable (Error) -> Void
- #else
- /// Adds an observer callback to this `EventLoopFuture` that is called when the
- /// `EventLoopFuture` has a failure result.
- ///
- /// An observer callback cannot return a value, meaning that this function cannot be chained
- /// from. If you are attempting to create a computation pipeline, consider `recover` or `flatMapError`.
- /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`
- /// in the body of this function, consider using `cascade` instead.
- ///
- /// - parameters:
- /// - callback: The callback that is called with the failed result of the `EventLoopFuture`.
- @inlinable
- public func whenFailure(_ callback: @escaping (Error) -> Void) {
- self._whenFailure(callback)
- }
- @usableFromInline typealias WhenFailureCallback = (Error) -> Void
- #endif
-
+
@inlinable
func _whenFailure(_ callback: @escaping WhenFailureCallback) {
self._whenComplete {
@@ -1054,7 +822,6 @@ extension EventLoopFuture {
}
}
- #if swift(>=5.7)
/// Adds an observer callback to this `EventLoopFuture` that is called when the
/// `EventLoopFuture` has any result.
///
@@ -1066,18 +833,6 @@ extension EventLoopFuture {
self._publicWhenComplete(callback)
}
@usableFromInline typealias WhenCompleteCallback = @Sendable (Result) -> Void
- #else
- /// Adds an observer callback to this `EventLoopFuture` that is called when the
- /// `EventLoopFuture` has any result.
- ///
- /// - parameters:
- /// - callback: The callback that is called when the `EventLoopFuture` is fulfilled.
- @inlinable
- public func whenComplete(_ callback: @escaping (Result) -> Void) {
- self._publicWhenComplete(callback)
- }
- @usableFromInline typealias WhenCompleteCallback = (Result) -> Void
- #endif
@inlinable
func _publicWhenComplete(_ callback: @escaping WhenCompleteCallback) {
self._whenComplete {
@@ -1223,7 +978,6 @@ extension EventLoopFuture {
// MARK: wait
extension EventLoopFuture {
- #if swift(>=5.7)
/// Wait for the resolution of this `EventLoopFuture` by blocking the current thread until it
/// resolves.
///
@@ -1242,25 +996,6 @@ extension EventLoopFuture {
public func wait(file: StaticString = #file, line: UInt = #line) throws -> Value {
return try self._wait(file: file, line: line)
}
- #else
- /// Wait for the resolution of this `EventLoopFuture` by blocking the current thread until it
- /// resolves.
- ///
- /// If the `EventLoopFuture` resolves with a value, that value is returned from `wait()`. If
- /// the `EventLoopFuture` resolves with an error, that error will be thrown instead.
- /// `wait()` will block whatever thread it is called on, so it must not be called on event loop
- /// threads: it is primarily useful for testing, or for building interfaces between blocking
- /// and non-blocking code.
- ///
- /// This is also forbidden in async contexts: prefer ``EventLoopFuture/get``.
- ///
- /// - returns: The value of the `EventLoopFuture` when it completes.
- /// - throws: The error value of the `EventLoopFuture` if it errors.
- @inlinable
- public func wait(file: StaticString = #file, line: UInt = #line) throws -> Value {
- return try self._wait(file: file, line: line)
- }
- #endif
@inlinable
func _wait(file: StaticString, line: UInt) throws -> Value {
@@ -1289,7 +1024,6 @@ extension EventLoopFuture {
// MARK: fold
extension EventLoopFuture {
- #if swift(>=5.7)
/// Returns a new `EventLoopFuture` that fires only when this `EventLoopFuture` and
/// all the provided `futures` complete. It then provides the result of folding the value of this
/// `EventLoopFuture` with the values of all the provided `futures`.
@@ -1315,33 +1049,7 @@ extension EventLoopFuture {
self._fold(futures, with: combiningFunction)
}
@usableFromInline typealias FoldCallback = @Sendable (Value, OtherValue) -> EventLoopFuture
- #else
- /// Returns a new `EventLoopFuture` that fires only when this `EventLoopFuture` and
- /// all the provided `futures` complete. It then provides the result of folding the value of this
- /// `EventLoopFuture` with the values of all the provided `futures`.
- ///
- /// This function is suited when you have APIs that already know how to return `EventLoopFuture`s.
- ///
- /// The returned `EventLoopFuture` will fail as soon as the a failure is encountered in any of the
- /// `futures` (or in this one). However, the failure will not occur until all preceding
- /// `EventLoopFutures` have completed. At the point the failure is encountered, all subsequent
- /// `EventLoopFuture` objects will no longer be waited for. This function therefore fails fast: once
- /// a failure is encountered, it will immediately fail the overall EventLoopFuture.
- ///
- /// - parameters:
- /// - futures: An array of `EventLoopFuture` to wait for.
- /// - with: A function that will be used to fold the values of two `EventLoopFuture`s and return a new value wrapped in an `EventLoopFuture`.
- /// - returns: A new `EventLoopFuture` with the folded value whose callbacks run on `self.eventLoop`.
- @inlinable
- public func fold(
- _ futures: [EventLoopFuture],
- with combiningFunction: @escaping (Value, OtherValue) -> EventLoopFuture
- ) -> EventLoopFuture {
- self._fold(futures, with: combiningFunction)
- }
- @usableFromInline typealias FoldCallback = (Value, OtherValue) -> EventLoopFuture
- #endif
-
+
@inlinable
func _fold(
_ futures: [EventLoopFuture],
@@ -1375,7 +1083,6 @@ extension EventLoopFuture {
// MARK: reduce
extension EventLoopFuture {
- #if swift(>=5.7)
/// Returns a new `EventLoopFuture` that fires only when all the provided futures complete.
/// The new `EventLoopFuture` contains the result of reducing the `initialResult` with the
/// values of the `[EventLoopFuture]`.
@@ -1406,38 +1113,7 @@ extension EventLoopFuture {
Self._reduce(initialResult, futures, on: eventLoop, nextPartialResult)
}
@usableFromInline typealias ReduceCallback = @Sendable (Value, InputValue) -> Value
- #else
- /// Returns a new `EventLoopFuture` that fires only when all the provided futures complete.
- /// The new `EventLoopFuture` contains the result of reducing the `initialResult` with the
- /// values of the `[EventLoopFuture]`.
- ///
- /// This function makes copies of the result for each EventLoopFuture, for a version which avoids
- /// making copies, check out `reduce(into:)`.
- ///
- /// The returned `EventLoopFuture` will fail as soon as a failure is encountered in any of the
- /// `futures`. However, the failure will not occur until all preceding
- /// `EventLoopFutures` have completed. At the point the failure is encountered, all subsequent
- /// `EventLoopFuture` objects will no longer be waited for. This function therefore fails fast: once
- /// a failure is encountered, it will immediately fail the overall `EventLoopFuture`.
- ///
- /// - parameters:
- /// - initialResult: An initial result to begin the reduction.
- /// - futures: An array of `EventLoopFuture` to wait for.
- /// - eventLoop: The `EventLoop` on which the new `EventLoopFuture` callbacks will fire.
- /// - nextPartialResult: The bifunction used to produce partial results.
- /// - returns: A new `EventLoopFuture` with the reduced value.
- @inlinable
- public static func reduce(
- _ initialResult: Value,
- _ futures: [EventLoopFuture],
- on eventLoop: EventLoop,
- _ nextPartialResult: @escaping (Value, InputValue) -> Value
- ) -> EventLoopFuture {
- Self._reduce(initialResult, futures, on: eventLoop, nextPartialResult)
- }
- @usableFromInline typealias ReduceCallback = (Value, InputValue) -> Value
- #endif
-
+
@inlinable
static func _reduce(
_ initialResult: Value,
@@ -1454,7 +1130,6 @@ extension EventLoopFuture {
return body
}
- #if swift(>=5.7)
/// Returns a new `EventLoopFuture` that fires only when all the provided futures complete.
/// The new `EventLoopFuture` contains the result of combining the `initialResult` with the
/// values of the `[EventLoopFuture]`. This function is analogous to the standard library's
@@ -1483,36 +1158,7 @@ extension EventLoopFuture {
Self._reduce(into: initialResult, futures, on: eventLoop, updateAccumulatingResult)
}
@usableFromInline typealias ReduceIntoCallback = @Sendable (inout Value, InputValue) -> Void
- #else
- /// Returns a new `EventLoopFuture` that fires only when all the provided futures complete.
- /// The new `EventLoopFuture` contains the result of combining the `initialResult` with the
- /// values of the `[EventLoopFuture]`. This function is analogous to the standard library's
- /// `reduce(into:)`, which does not make copies of the result type for each `EventLoopFuture`.
- ///
- /// The returned `EventLoopFuture` will fail as soon as a failure is encountered in any of the
- /// `futures`. However, the failure will not occur until all preceding
- /// `EventLoopFutures` have completed. At the point the failure is encountered, all subsequent
- /// `EventLoopFuture` objects will no longer be waited for. This function therefore fails fast: once
- /// a failure is encountered, it will immediately fail the overall `EventLoopFuture`.
- ///
- /// - parameters:
- /// - initialResult: An initial result to begin the reduction.
- /// - futures: An array of `EventLoopFuture` to wait for.
- /// - eventLoop: The `EventLoop` on which the new `EventLoopFuture` callbacks will fire.
- /// - updateAccumulatingResult: The bifunction used to combine partialResults with new elements.
- /// - returns: A new `EventLoopFuture` with the combined value.
- @inlinable
- public static func reduce(
- into initialResult: Value,
- _ futures: [EventLoopFuture],
- on eventLoop: EventLoop,
- _ updateAccumulatingResult: @escaping (inout Value, InputValue) -> Void
- ) -> EventLoopFuture {
- Self._reduce(into: initialResult, futures, on: eventLoop, updateAccumulatingResult)
- }
- @usableFromInline typealias ReduceIntoCallback = (inout Value, InputValue) -> Void
- #endif
-
+
@inlinable
static func _reduce(
into initialResult: Value,
@@ -1611,15 +1257,9 @@ extension EventLoopFuture {
let reduced = eventLoop.makePromise(of: Void.self)
let results: UnsafeMutableTransferBox<[Value?]> = .init(.init(repeating: nil, count: futures.count))
- #if swift(>=5.7)
let callback = { @Sendable (index: Int, result: Value) in
results.wrappedValue[index] = result
}
- #else
- let callback = { (index: Int, result: Value) in
- results.wrappedValue[index] = result
- }
- #endif
if eventLoop.inEventLoop {
self._reduceSuccesses0(reduced, futures, eventLoop, onValue: callback)
@@ -1640,12 +1280,8 @@ extension EventLoopFuture {
}
}
}
-
- #if swift(>=5.7)
+
@usableFromInline typealias ReduceSuccessCallback = @Sendable (Int, InputValue) -> Void
- #else
- @usableFromInline typealias ReduceSuccessCallback = (Int, InputValue) -> Void
- #endif
/// Loops through the futures array and attaches callbacks to execute `onValue` on the provided `EventLoop` when
/// they succeed. The `onValue` will receive the index of the future that fulfilled the provided `Result`.
///
@@ -1773,17 +1409,11 @@ extension EventLoopFuture {
promise: EventLoopPromise<[Result]>) {
let eventLoop = promise.futureResult.eventLoop
let reduced = eventLoop.makePromise(of: Void.self)
-
+
let results: UnsafeMutableTransferBox<[Result]> = .init(.init(repeating: .failure(OperationPlaceholderError()), count: futures.count))
- #if swift(>=5.7)
let callback = { @Sendable (index: Int, result: Result) in
results.wrappedValue[index] = result
}
- #else
- let callback = { (index: Int, result: Result) in
- results.wrappedValue[index] = result
- }
- #endif
if eventLoop.inEventLoop {
self._reduceCompletions0(reduced, futures, eventLoop, onResult: callback)
@@ -1808,13 +1438,9 @@ extension EventLoopFuture {
}
}
}
-
- #if swift(>=5.7)
+
@usableFromInline typealias ReduceCompletions = @Sendable (Int, Result) -> Void
- #else
- @usableFromInline typealias ReduceCompletions = (Int, Result) -> Void
- #endif
-
+
/// Loops through the futures array and attaches callbacks to execute `onResult` on the provided `EventLoop` when
/// they complete. The `onResult` will receive the index of the future that fulfilled the provided `Result`.
///
@@ -1889,7 +1515,6 @@ extension EventLoopFuture {
// MARK: always
extension EventLoopFuture {
- #if swift(>=5.7)
/// Adds an observer callback to this `EventLoopFuture` that is called when the
/// `EventLoopFuture` has any result.
///
@@ -1902,20 +1527,7 @@ extension EventLoopFuture {
self._always(callback)
}
@usableFromInline typealias AlwaysCallback = @Sendable (Result) -> Void
- #else
- /// Adds an observer callback to this `EventLoopFuture` that is called when the
- /// `EventLoopFuture` has any result.
- ///
- /// - parameters:
- /// - callback: the callback that is called when the `EventLoopFuture` is fulfilled.
- /// - returns: the current `EventLoopFuture`
- @inlinable
- public func always(_ callback: @escaping (Result) -> Void) -> EventLoopFuture {
- self._always(callback)
- }
- @usableFromInline typealias AlwaysCallback = (Result) -> Void
- #endif
-
+
@inlinable
func _always(_ callback: @escaping AlwaysCallback) -> EventLoopFuture {
self.whenComplete { result in callback(result) }
@@ -1974,8 +1586,7 @@ extension EventLoopFuture {
return value
}
}
-
- #if swift(>=5.7)
+
/// Unwrap an `EventLoopFuture` where its type parameter is an `Optional`.
///
/// Unwraps a future returning a new `EventLoopFuture` with either: the value returned by the closure passed in
@@ -1998,30 +1609,7 @@ extension EventLoopFuture {
self._unwrap(orElse: callback)
}
@usableFromInline typealias UnwrapCallback = @Sendable () -> NewValue
- #else
- /// Unwrap an `EventLoopFuture` where its type parameter is an `Optional`.
- ///
- /// Unwraps a future returning a new `EventLoopFuture` with either: the value returned by the closure passed in
- /// the `orElse` parameter when the future resolved with value Optional.none, or the same value otherwise. For example:
- /// ```
- /// var x = 2
- /// promise.futureResult.unwrap(orElse: { x * 2 }).wait()
- /// ```
- ///
- /// - parameters:
- /// - orElse: a closure that returns the value of the returned `EventLoopFuture` when then resolved future's value
- /// is `Optional.some()`.
- /// - returns: an new `EventLoopFuture` with new type parameter `NewValue` and with the value returned by the closure
- /// passed in the `orElse` parameter.
- @inlinable
- public func unwrap(
- orElse callback: @escaping () -> NewValue
- ) -> EventLoopFuture where Value == Optional {
- self._unwrap(orElse: callback)
- }
- @usableFromInline typealias UnwrapCallback = () -> NewValue
- #endif
-
+
@inlinable
func _unwrap(
orElse callback: @escaping UnwrapCallback
@@ -2038,7 +1626,6 @@ extension EventLoopFuture {
// MARK: may block
extension EventLoopFuture {
- #if swift(>=5.7)
/// Chain an `EventLoopFuture` providing the result of a IO / task that may block. For example:
///
/// promise.futureResult.flatMapBlocking(onto: DispatchQueue.global()) { value in Int
@@ -2058,27 +1645,7 @@ extension EventLoopFuture {
self._flatMapBlocking(onto: queue, callbackMayBlock)
}
@usableFromInline typealias FlatMapBlockingCallback = @Sendable (Value) throws -> NewValue
- #else
- /// Chain an `EventLoopFuture` providing the result of a IO / task that may block. For example:
- ///
- /// promise.futureResult.flatMapBlocking(onto: DispatchQueue.global()) { value in Int
- /// blockingTask(value)
- /// }
- ///
- /// - parameters:
- /// - onto: the `DispatchQueue` on which the blocking IO / task specified by `callbackMayBlock` is scheduled.
- /// - callbackMayBlock: Function that will receive the value of this `EventLoopFuture` and return
- /// a new `EventLoopFuture`.
- @inlinable
- public func flatMapBlocking(
- onto queue: DispatchQueue,
- _ callbackMayBlock: @escaping (Value) throws -> NewValue
- ) -> EventLoopFuture {
- self._flatMapBlocking(onto: queue, callbackMayBlock)
- }
- @usableFromInline typealias FlatMapBlockingCallback = (Value) throws -> NewValue
- #endif
-
+
@inlinable
func _flatMapBlocking(
onto queue: DispatchQueue,
@@ -2088,7 +1655,7 @@ extension EventLoopFuture {
queue.asyncWithFuture(eventLoop: self.eventLoop) { try callbackMayBlock(result) }
}
}
-
+
/// Adds an observer callback to this `EventLoopFuture` that is called when the
/// `EventLoopFuture` has a success result. The observer callback is permitted to block.
///
@@ -2106,8 +1673,7 @@ extension EventLoopFuture {
queue.async { callbackMayBlock(value) }
}
}
-
- #if swift(>=5.7)
+
/// Adds an observer callback to this `EventLoopFuture` that is called when the
/// `EventLoopFuture` has a failure result. The observer callback is permitted to block.
///
@@ -2125,34 +1691,14 @@ extension EventLoopFuture {
self._whenFailureBlocking(onto: queue, callbackMayBlock)
}
@usableFromInline typealias WhenFailureBlockingCallback = @Sendable (Error) -> Void
- #else
- /// Adds an observer callback to this `EventLoopFuture` that is called when the
- /// `EventLoopFuture` has a failure result. The observer callback is permitted to block.
- ///
- /// An observer callback cannot return a value, meaning that this function cannot be chained
- /// from. If you are attempting to create a computation pipeline, consider `recover` or `flatMapError`.
- /// If you find yourself passing the results from this `EventLoopFuture` to a new `EventLoopPromise`
- /// in the body of this function, consider using `cascade` instead.
- ///
- /// - parameters:
- /// - onto: the `DispatchQueue` on which the blocking IO / task specified by `callbackMayBlock` is scheduled.
- /// - callbackMayBlock: The callback that is called with the failed result of the `EventLoopFuture`.
- @inlinable
- public func whenFailureBlocking(onto queue: DispatchQueue, _ callbackMayBlock: @escaping (Error) -> Void) {
- self._whenFailureBlocking(onto: queue, callbackMayBlock)
- }
- @usableFromInline typealias WhenFailureBlockingCallback = (Error) -> Void
- #endif
-
+
@inlinable
func _whenFailureBlocking(onto queue: DispatchQueue, _ callbackMayBlock: @escaping WhenFailureBlockingCallback) {
self.whenFailure { err in
queue.async { callbackMayBlock(err) }
}
}
-
- #if swift(>=5.7)
/// Adds an observer callback to this `EventLoopFuture` that is called when the
/// `EventLoopFuture` has any result. The observer callback is permitted to block.
///
@@ -2165,20 +1711,7 @@ extension EventLoopFuture {
self._whenCompleteBlocking(onto: queue, callbackMayBlock)
}
@usableFromInline typealias WhenCompleteBlocking = @Sendable (Result) -> Void
- #else
- /// Adds an observer callback to this `EventLoopFuture` that is called when the
- /// `EventLoopFuture` has any result. The observer callback is permitted to block.
- ///
- /// - parameters:
- /// - onto: the `DispatchQueue` on which the blocking IO / task specified by `callbackMayBlock` is scheduled.
- /// - callbackMayBlock: The callback that is called when the `EventLoopFuture` is fulfilled.
- @inlinable
- public func whenCompleteBlocking(onto queue: DispatchQueue, _ callbackMayBlock: @escaping (Result) -> Void) {
- self._whenCompleteBlocking(onto: queue, callbackMayBlock)
- }
- @usableFromInline typealias WhenCompleteBlocking = (Result) -> Void
- #endif
-
+
@inlinable
func _whenCompleteBlocking(onto queue: DispatchQueue, _ callbackMayBlock: @escaping WhenCompleteBlocking) {
self.whenComplete { value in
@@ -2283,7 +1816,6 @@ public struct _NIOEventLoopFutureIdentifier: Hashable, Sendable {
self.opaqueID = _NIOEventLoopFutureIdentifier.obfuscatePointerValue(future: future)
}
-
private static func obfuscatePointerValue(future: EventLoopFuture) -> UInt {
// Note:
// 1. 0xbf15ca5d is randomly picked such that it fits into both 32 and 64 bit address spaces
diff --git a/Sources/NIOCore/SingleStepByteToMessageDecoder.swift b/Sources/NIOCore/SingleStepByteToMessageDecoder.swift
index 5cda5a579..2341a0550 100644
--- a/Sources/NIOCore/SingleStepByteToMessageDecoder.swift
+++ b/Sources/NIOCore/SingleStepByteToMessageDecoder.swift
@@ -274,10 +274,8 @@ public final class NIOSingleStepByteToMessageProcessor=5.7)
@available(*, unavailable)
extension NIOSingleStepByteToMessageProcessor: Sendable {}
-#endif
// MARK: NIOSingleStepByteToMessageProcessor Public API
extension NIOSingleStepByteToMessageProcessor {
diff --git a/Sources/NIOCore/UniversalBootstrapSupport.swift b/Sources/NIOCore/UniversalBootstrapSupport.swift
index 01ab959e1..b89594a20 100644
--- a/Sources/NIOCore/UniversalBootstrapSupport.swift
+++ b/Sources/NIOCore/UniversalBootstrapSupport.swift
@@ -15,7 +15,6 @@
/// `NIOClientTCPBootstrapProtocol` is implemented by various underlying transport mechanisms. Typically,
/// this will be the BSD Sockets API implemented by `ClientBootstrap`.
public protocol NIOClientTCPBootstrapProtocol {
- #if swift(>=5.7)
/// Initialize the connected `SocketChannel` with `initializer`. The most common task in initializer is to add
/// `ChannelHandler`s to the `ChannelPipeline`.
///
@@ -35,28 +34,7 @@ public protocol NIOClientTCPBootstrapProtocol {
/// - handler: A closure that initializes the provided `Channel`.
@preconcurrency
func channelInitializer(_ handler: @escaping @Sendable (Channel) -> EventLoopFuture) -> Self
- #else
- /// Initialize the connected `SocketChannel` with `initializer`. The most common task in initializer is to add
- /// `ChannelHandler`s to the `ChannelPipeline`.
- ///
- /// The connected `Channel` will operate on `ByteBuffer` as inbound and `IOData` as outbound messages.
- ///
- /// - warning: The `handler` closure may be invoked _multiple times_ so it's usually the right choice to instantiate
- /// `ChannelHandler`s within `handler`. The reason `handler` may be invoked multiple times is that to
- /// successfully set up a connection multiple connections might be setup in the process. Assuming a
- /// hostname that resolves to both IPv4 and IPv6 addresses, NIO will follow
- /// [_Happy Eyeballs_](https://en.wikipedia.org/wiki/Happy_Eyeballs) and race both an IPv4 and an IPv6
- /// connection. It is possible that both connections get fully established before the IPv4 connection
- /// will be closed again because the IPv6 connection 'won the race'. Therefore the `channelInitializer`
- /// might be called multiple times and it's important not to share stateful `ChannelHandler`s in more
- /// than one `Channel`.
- ///
- /// - parameters:
- /// - handler: A closure that initializes the provided `Channel`.
- func channelInitializer(_ handler: @escaping (Channel) -> EventLoopFuture) -> Self
- #endif
-
- #if swift(>=5.7)
+
/// Sets the protocol handlers that will be added to the front of the `ChannelPipeline` right after the
/// `channelInitializer` has been called.
///
@@ -65,15 +43,6 @@ public protocol NIOClientTCPBootstrapProtocol {
/// `protocolHandlers` to add the required `ChannelHandler`s for many TLS implementations.
@preconcurrency
func protocolHandlers(_ handlers: @escaping @Sendable () -> [ChannelHandler]) -> Self
- #else
- /// Sets the protocol handlers that will be added to the front of the `ChannelPipeline` right after the
- /// `channelInitializer` has been called.
- ///
- /// Per bootstrap, you can only set the `protocolHandlers` once. Typically, `protocolHandlers` are used for the TLS
- /// implementation. Most notably, `NIOClientTCPBootstrap`, NIO's "universal bootstrap" abstraction, uses
- /// `protocolHandlers` to add the required `ChannelHandler`s for many TLS implementations.
- func protocolHandlers(_ handlers: @escaping () -> [ChannelHandler]) -> Self
- #endif
/// Specifies a `ChannelOption` to be applied to the `SocketChannel`.
///
@@ -81,7 +50,7 @@ public protocol NIOClientTCPBootstrapProtocol {
/// - option: The option to be applied.
/// - value: The value for the option.
func channelOption(_ option: Option, value: Option.Value) -> Self
-
+
/// Apply any understood convenience options to the bootstrap, removing them from the set of options if they are consumed.
/// Method is optional to implement and should never be directly called by users.
/// - parameters:
@@ -198,7 +167,7 @@ public struct NIOClientTCPBootstrap {
self.underlyingBootstrap = bootstrap
self.tlsEnablerTypeErased = tlsEnabler
}
-
+
internal init(_ original : NIOClientTCPBootstrap, updating underlying : NIOClientTCPBootstrapProtocol) {
self.underlyingBootstrap = underlying
self.tlsEnablerTypeErased = original.tlsEnablerTypeErased
diff --git a/Sources/NIOHTTP1/HTTPPipelineSetup.swift b/Sources/NIOHTTP1/HTTPPipelineSetup.swift
index 251143f95..c433665af 100644
--- a/Sources/NIOHTTP1/HTTPPipelineSetup.swift
+++ b/Sources/NIOHTTP1/HTTPPipelineSetup.swift
@@ -14,19 +14,11 @@
import NIOCore
-#if swift(>=5.7)
/// Configuration required to configure a HTTP client pipeline for upgrade.
///
/// See the documentation for `HTTPClientUpgradeHandler` for details on these
/// properties.
public typealias NIOHTTPClientUpgradeConfiguration = (upgraders: [NIOHTTPClientProtocolUpgrader], completionHandler: @Sendable (ChannelHandlerContext) -> Void)
-#else
-/// Configuration required to configure a HTTP client pipeline for upgrade.
-///
-/// See the documentation for `HTTPClientUpgradeHandler` for details on these
-/// properties.
-public typealias NIOHTTPClientUpgradeConfiguration = (upgraders: [NIOHTTPClientProtocolUpgrader], completionHandler: (ChannelHandlerContext) -> Void)
-#endif
/// Configuration required to configure a HTTP server pipeline for upgrade.
///
@@ -35,11 +27,7 @@ public typealias NIOHTTPClientUpgradeConfiguration = (upgraders: [NIOHTTPClientP
@available(*, deprecated, renamed: "NIOHTTPServerUpgradeConfiguration")
public typealias HTTPUpgradeConfiguration = NIOHTTPServerUpgradeConfiguration
-#if swift(>=5.7)
public typealias NIOHTTPServerUpgradeConfiguration = (upgraders: [HTTPServerProtocolUpgrader], completionHandler: @Sendable (ChannelHandlerContext) -> Void)
-#else
-public typealias NIOHTTPServerUpgradeConfiguration = (upgraders: [HTTPServerProtocolUpgrader], completionHandler: (ChannelHandlerContext) -> Void)
-#endif
extension ChannelPipeline {
/// Configure a `ChannelPipeline` for use as a HTTP client.
@@ -56,7 +44,6 @@ extension ChannelPipeline {
withClientUpgrade: nil)
}
- #if swift(>=5.7)
/// Configure a `ChannelPipeline` for use as a HTTP client with a client upgrader configuration.
///
/// - parameters:
@@ -78,29 +65,7 @@ extension ChannelPipeline {
withClientUpgrade: upgrade
)
}
- #else
- /// Configure a `ChannelPipeline` for use as a HTTP client with a client upgrader configuration.
- ///
- /// - parameters:
- /// - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.
- /// - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`
- /// from the pipeline.
- /// - upgrade: Add a `HTTPClientUpgradeHandler` to the pipeline, configured for
- /// HTTP upgrade. Should be a tuple of an array of `HTTPClientProtocolUpgrader` and
- /// the upgrade completion handler. See the documentation on `HTTPClientUpgradeHandler`
- /// for more details.
- /// - returns: An `EventLoopFuture` that will fire when the pipeline is configured.
- public func addHTTPClientHandlers(position: Position = .last,
- leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,
- withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration?) -> EventLoopFuture {
- self._addHTTPClientHandlers(
- position: position,
- leftOverBytesStrategy: leftOverBytesStrategy,
- withClientUpgrade: upgrade
- )
- }
- #endif
-
+
private func _addHTTPClientHandlers(position: Position = .last,
leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,
withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration?) -> EventLoopFuture {
@@ -206,7 +171,6 @@ extension ChannelPipeline {
return future
}
- #if swift(>=5.7)
/// Configure a `ChannelPipeline` for use as a HTTP server.
///
/// This function knows how to set up all first-party HTTP channel handlers appropriately
@@ -244,44 +208,6 @@ extension ChannelPipeline {
withErrorHandling: errorHandling
)
}
- #else
- /// Configure a `ChannelPipeline` for use as a HTTP server.
- ///
- /// This function knows how to set up all first-party HTTP channel handlers appropriately
- /// for server use. It supports the following features:
- ///
- /// 1. Providing assistance handling clients that pipeline HTTP requests, using the
- /// `HTTPServerPipelineHandler`.
- /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.
- ///
- /// This method will likely be extended in future with more support for other first-party
- /// features.
- ///
- /// - parameters:
- /// - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.
- /// - pipelining: Whether to provide assistance handling HTTP clients that pipeline
- /// their requests. Defaults to `true`. If `false`, users will need to handle
- /// clients that pipeline themselves.
- /// - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for
- /// HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If
- /// provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade
- /// completion handler. See the documentation on `HTTPServerUpgradeHandler` for more
- /// details.
- /// - errorHandling: Whether to provide assistance handling protocol errors (e.g.
- /// failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.
- /// - returns: An `EventLoopFuture` that will fire when the pipeline is configured.
- public func configureHTTPServerPipeline(position: ChannelPipeline.Position = .last,
- withPipeliningAssistance pipelining: Bool = true,
- withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,
- withErrorHandling errorHandling: Bool = true) -> EventLoopFuture {
- self._configureHTTPServerPipeline(
- position: position,
- withPipeliningAssistance: pipelining,
- withServerUpgrade: upgrade,
- withErrorHandling: errorHandling
- )
- }
- #endif
/// Configure a `ChannelPipeline` for use as a HTTP server.
///
@@ -410,7 +336,6 @@ extension ChannelPipeline {
}
extension ChannelPipeline.SynchronousOperations {
- #if swift(>=5.7)
/// Configure a `ChannelPipeline` for use as a HTTP client with a client upgrader configuration.
///
/// - important: This **must** be called on the Channel's event loop.
@@ -433,29 +358,6 @@ extension ChannelPipeline.SynchronousOperations {
withClientUpgrade: upgrade
)
}
- #else
- /// Configure a `ChannelPipeline` for use as a HTTP client with a client upgrader configuration.
- ///
- /// - important: This **must** be called on the Channel's event loop.
- /// - parameters:
- /// - position: The position in the `ChannelPipeline` where to add the HTTP client handlers. Defaults to `.last`.
- /// - leftOverBytesStrategy: The strategy to use when dealing with leftover bytes after removing the `HTTPDecoder`
- /// from the pipeline.
- /// - upgrade: Add a `HTTPClientUpgradeHandler` to the pipeline, configured for
- /// HTTP upgrade. Should be a tuple of an array of `HTTPClientProtocolUpgrader` and
- /// the upgrade completion handler. See the documentation on `HTTPClientUpgradeHandler`
- /// for more details.
- /// - throws: If the pipeline could not be configured.
- public func addHTTPClientHandlers(position: ChannelPipeline.Position = .last,
- leftOverBytesStrategy: RemoveAfterUpgradeStrategy = .dropBytes,
- withClientUpgrade upgrade: NIOHTTPClientUpgradeConfiguration? = nil) throws {
- try self._addHTTPClientHandlers(
- position: position,
- leftOverBytesStrategy: leftOverBytesStrategy,
- withClientUpgrade: upgrade
- )
- }
- #endif
/// Configure a `ChannelPipeline` for use as a HTTP client.
///
@@ -558,7 +460,6 @@ extension ChannelPipeline.SynchronousOperations {
try self.addHandlers(handlers, position: position)
}
- #if swift(>=5.7)
/// Configure a `ChannelPipeline` for use as a HTTP server.
///
/// This function knows how to set up all first-party HTTP channel handlers appropriately
@@ -597,45 +498,6 @@ extension ChannelPipeline.SynchronousOperations {
withErrorHandling: errorHandling
)
}
- #else
- /// Configure a `ChannelPipeline` for use as a HTTP server.
- ///
- /// This function knows how to set up all first-party HTTP channel handlers appropriately
- /// for server use. It supports the following features:
- ///
- /// 1. Providing assistance handling clients that pipeline HTTP requests, using the
- /// `HTTPServerPipelineHandler`.
- /// 2. Supporting HTTP upgrade, using the `HTTPServerUpgradeHandler`.
- ///
- /// This method will likely be extended in future with more support for other first-party
- /// features.
- ///
- /// - important: This **must** be called on the Channel's event loop.
- /// - parameters:
- /// - position: Where in the pipeline to add the HTTP server handlers, defaults to `.last`.
- /// - pipelining: Whether to provide assistance handling HTTP clients that pipeline
- /// their requests. Defaults to `true`. If `false`, users will need to handle
- /// clients that pipeline themselves.
- /// - upgrade: Whether to add a `HTTPServerUpgradeHandler` to the pipeline, configured for
- /// HTTP upgrade. Defaults to `nil`, which will not add the handler to the pipeline. If
- /// provided should be a tuple of an array of `HTTPServerProtocolUpgrader` and the upgrade
- /// completion handler. See the documentation on `HTTPServerUpgradeHandler` for more
- /// details.
- /// - errorHandling: Whether to provide assistance handling protocol errors (e.g.
- /// failure to parse the HTTP request) by sending 400 errors. Defaults to `true`.
- /// - throws: If the pipeline could not be configured.
- public func configureHTTPServerPipeline(position: ChannelPipeline.Position = .last,
- withPipeliningAssistance pipelining: Bool = true,
- withServerUpgrade upgrade: NIOHTTPServerUpgradeConfiguration? = nil,
- withErrorHandling errorHandling: Bool = true) throws {
- try self._configureHTTPServerPipeline(
- position: position,
- withPipeliningAssistance: pipelining,
- withServerUpgrade: upgrade,
- withErrorHandling: errorHandling
- )
- }
- #endif
/// Configure a `ChannelPipeline` for use as a HTTP server.
///
diff --git a/Sources/NIOPosix/Bootstrap.swift b/Sources/NIOPosix/Bootstrap.swift
index 0e90bb85d..7d5c2a660 100644
--- a/Sources/NIOPosix/Bootstrap.swift
+++ b/Sources/NIOPosix/Bootstrap.swift
@@ -25,13 +25,8 @@ import struct WinSDK.DWORD
import struct WinSDK.HANDLE
#endif
-#if swift(>=5.7)
/// The type of all `channelInitializer` callbacks.
internal typealias ChannelInitializerCallback = @Sendable (Channel) -> EventLoopFuture
-#else
-/// The type of all `channelInitializer` callbacks.
-internal typealias ChannelInitializerCallback = (Channel) -> EventLoopFuture
-#endif
/// Common functionality for all NIO on sockets bootstraps.
internal enum NIOOnSocketsBootstraps {
@@ -151,7 +146,6 @@ public final class ServerBootstrap {
self.enableMPTCP = false
}
- #if swift(>=5.7)
/// Initialize the `ServerSocketChannel` with `initializer`. The most common task in initializer is to add
/// `ChannelHandler`s to the `ChannelPipeline`.
///
@@ -166,23 +160,7 @@ public final class ServerBootstrap {
self.serverChannelInit = initializer
return self
}
- #else
- /// Initialize the `ServerSocketChannel` with `initializer`. The most common task in initializer is to add
- /// `ChannelHandler`s to the `ChannelPipeline`.
- ///
- /// The `ServerSocketChannel` uses the accepted `Channel`s as inbound messages.
- ///
- /// - note: To set the initializer for the accepted `SocketChannel`s, look at `ServerBootstrap.childChannelInitializer`.
- ///
- /// - parameters:
- /// - initializer: A closure that initializes the provided `Channel`.
- public func serverChannelInitializer(_ initializer: @escaping (Channel) -> EventLoopFuture) -> Self {
- self.serverChannelInit = initializer
- return self
- }
- #endif
- #if swift(>=5.7)
/// Initialize the accepted `SocketChannel`s with `initializer`. The most common task in initializer is to add
/// `ChannelHandler`s to the `ChannelPipeline`. Note that if the `initializer` fails then the error will be
/// fired in the *parent* channel.
@@ -202,26 +180,6 @@ public final class ServerBootstrap {
self.childChannelInit = initializer
return self
}
- #else
- /// Initialize the accepted `SocketChannel`s with `initializer`. The most common task in initializer is to add
- /// `ChannelHandler`s to the `ChannelPipeline`. Note that if the `initializer` fails then the error will be
- /// fired in the *parent* channel.
- ///
- /// - warning: The `initializer` will be invoked once for every accepted connection. Therefore it's usually the
- /// right choice to instantiate stateful `ChannelHandler`s within the closure to make sure they are not
- /// accidentally shared across `Channel`s. There are expert use-cases where stateful handler need to be
- /// shared across `Channel`s in which case the user is responsible to synchronise the state access
- /// appropriately.
- ///
- /// The accepted `Channel` will operate on `ByteBuffer` as inbound and `IOData` as outbound messages.
- ///
- /// - parameters:
- /// - initializer: A closure that initializes the provided `Channel`.
- public func childChannelInitializer(_ initializer: @escaping (Channel) -> EventLoopFuture) -> Self {
- self.childChannelInit = initializer
- return self
- }
- #endif
/// Specifies a `ChannelOption` to be applied to the `ServerSocketChannel`.
///
@@ -738,11 +696,7 @@ private extension Channel {
/// The connected `SocketChannel` will operate on `ByteBuffer` as inbound and on `IOData` as outbound messages.
public final class ClientBootstrap: NIOClientTCPBootstrapProtocol {
private let group: EventLoopGroup
- #if swift(>=5.7)
private var protocolHandlers: Optional<@Sendable () -> [ChannelHandler]>
- #else
- private var protocolHandlers: Optional<() -> [ChannelHandler]>
- #endif
private var _channelInitializer: ChannelInitializerCallback
private var channelInitializer: ChannelInitializerCallback {
if let protocolHandlers = self.protocolHandlers {
@@ -798,7 +752,6 @@ public final class ClientBootstrap: NIOClientTCPBootstrapProtocol {
self.enableMPTCP = false
}
- #if swift(>=5.7)
/// Initialize the connected `SocketChannel` with `initializer`. The most common task in initializer is to add
/// `ChannelHandler`s to the `ChannelPipeline`.
///
@@ -821,31 +774,7 @@ public final class ClientBootstrap: NIOClientTCPBootstrapProtocol {
self._channelInitializer = handler
return self
}
- #else
- /// Initialize the connected `SocketChannel` with `initializer`. The most common task in initializer is to add
- /// `ChannelHandler`s to the `ChannelPipeline`.
- ///
- /// The connected `Channel` will operate on `ByteBuffer` as inbound and `IOData` as outbound messages.
- ///
- /// - warning: The `handler` closure may be invoked _multiple times_ so it's usually the right choice to instantiate
- /// `ChannelHandler`s within `handler`. The reason `handler` may be invoked multiple times is that to
- /// successfully set up a connection multiple connections might be setup in the process. Assuming a
- /// hostname that resolves to both IPv4 and IPv6 addresses, NIO will follow
- /// [_Happy Eyeballs_](https://en.wikipedia.org/wiki/Happy_Eyeballs) and race both an IPv4 and an IPv6
- /// connection. It is possible that both connections get fully established before the IPv4 connection
- /// will be closed again because the IPv6 connection 'won the race'. Therefore the `channelInitializer`
- /// might be called multiple times and it's important not to share stateful `ChannelHandler`s in more
- /// than one `Channel`.
- ///
- /// - parameters:
- /// - handler: A closure that initializes the provided `Channel`.
- public func channelInitializer(_ handler: @escaping (Channel) -> EventLoopFuture) -> Self {
- self._channelInitializer = handler
- return self
- }
- #endif
- #if swift(>=5.7)
/// Sets the protocol handlers that will be added to the front of the `ChannelPipeline` right after the
/// `channelInitializer` has been called.
///
@@ -858,19 +787,6 @@ public final class ClientBootstrap: NIOClientTCPBootstrapProtocol {
self.protocolHandlers = handlers
return self
}
- #else
- /// Sets the protocol handlers that will be added to the front of the `ChannelPipeline` right after the
- /// `channelInitializer` has been called.
- ///
- /// Per bootstrap, you can only set the `protocolHandlers` once. Typically, `protocolHandlers` are used for the TLS
- /// implementation. Most notably, `NIOClientTCPBootstrap`, NIO's "universal bootstrap" abstraction, uses
- /// `protocolHandlers` to add the required `ChannelHandler`s for many TLS implementations.
- public func protocolHandlers(_ handlers: @escaping () -> [ChannelHandler]) -> Self {
- precondition(self.protocolHandlers == nil, "protocol handlers can only be set once")
- self.protocolHandlers = handlers
- return self
- }
- #endif
/// Specifies a `ChannelOption` to be applied to the `SocketChannel`.
///
@@ -1435,7 +1351,6 @@ public final class DatagramBootstrap {
self.channelInitializer = nil
}
- #if swift(>=5.7)
/// Initialize the bound `DatagramChannel` with `initializer`. The most common task in initializer is to add
/// `ChannelHandler`s to the `ChannelPipeline`.
///
@@ -1446,17 +1361,6 @@ public final class DatagramBootstrap {
self.channelInitializer = handler
return self
}
- #else
- /// Initialize the bound `DatagramChannel` with `initializer`. The most common task in initializer is to add
- /// `ChannelHandler`s to the `ChannelPipeline`.
- ///
- /// - parameters:
- /// - handler: A closure that initializes the provided `Channel`.
- public func channelInitializer(_ handler: @escaping (Channel) -> EventLoopFuture) -> Self {
- self.channelInitializer = handler
- return self
- }
- #endif
/// Specifies a `ChannelOption` to be applied to the `DatagramChannel`.
///
@@ -1998,7 +1902,6 @@ public final class NIOPipeBootstrap {
self.channelInitializer = nil
}
- #if swift(>=5.7)
/// Initialize the connected `PipeChannel` with `initializer`. The most common task in initializer is to add
/// `ChannelHandler`s to the `ChannelPipeline`.
///
@@ -2012,20 +1915,6 @@ public final class NIOPipeBootstrap {
self.channelInitializer = handler
return self
}
- #else
- /// Initialize the connected `PipeChannel` with `initializer`. The most common task in initializer is to add
- /// `ChannelHandler`s to the `ChannelPipeline`.
- ///
- /// The connected `Channel` will operate on `ByteBuffer` as inbound and outbound messages. Please note that
- /// `IOData.fileRegion` is _not_ supported for `PipeChannel`s because `sendfile` only works on sockets.
- ///
- /// - parameters:
- /// - handler: A closure that initializes the provided `Channel`.
- public func channelInitializer(_ handler: @escaping (Channel) -> EventLoopFuture) -> Self {
- self.channelInitializer = handler
- return self
- }
- #endif
/// Specifies a `ChannelOption` to be applied to the `PipeChannel`.
///
@@ -2207,7 +2096,7 @@ extension NIOPipeBootstrap {
throw error
}
}
-
+
/// Create the `PipeChannel` with the provided input and output file descriptors.
///
/// The input and output file descriptors must be distinct. If you have a single file descriptor, consider using
@@ -2240,7 +2129,7 @@ extension NIOPipeBootstrap {
postRegisterTransformation: { $0.makeSucceededFuture($1) }
)
}
-
+
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
@_spi(AsyncChannel) // Should become private
public func _takingOwnershipOfDescriptors(
diff --git a/Sources/NIOPosix/MultiThreadedEventLoopGroup.swift b/Sources/NIOPosix/MultiThreadedEventLoopGroup.swift
index f9214a5f9..8c85a873f 100644
--- a/Sources/NIOPosix/MultiThreadedEventLoopGroup.swift
+++ b/Sources/NIOPosix/MultiThreadedEventLoopGroup.swift
@@ -53,12 +53,8 @@ typealias ThreadInitializer = (NIOThread) -> Void
/// test. A good place to start a `MultiThreadedEventLoopGroup` is the `setUp` method of your `XCTestCase`
/// subclass, a good place to shut it down is the `tearDown` method.
public final class MultiThreadedEventLoopGroup: EventLoopGroup {
- #if swift(>=5.7)
private typealias ShutdownGracefullyCallback = @Sendable (Error?) -> Void
- #else
- private typealias ShutdownGracefullyCallback = (Error?) -> Void
- #endif
-
+
private enum RunState {
case running
case closing([(DispatchQueue, ShutdownGracefullyCallback)])
@@ -262,7 +258,6 @@ public final class MultiThreadedEventLoopGroup: EventLoopGroup {
}
}
- #if swift(>=5.7)
/// Shut this `MultiThreadedEventLoopGroup` down which causes the `EventLoop`s and their associated threads to be
/// shut down and release their resources.
///
@@ -277,22 +272,7 @@ public final class MultiThreadedEventLoopGroup: EventLoopGroup {
public func shutdownGracefully(queue: DispatchQueue, _ handler: @escaping @Sendable (Error?) -> Void) {
self._shutdownGracefully(queue: queue, handler)
}
- #else
- /// Shut this `MultiThreadedEventLoopGroup` down which causes the `EventLoop`s and their associated threads to be
- /// shut down and release their resources.
- ///
- /// Even though calling `shutdownGracefully` more than once should be avoided, it is safe to do so and execution
- /// of the `handler` is guaranteed.
- ///
- /// - parameters:
- /// - queue: The `DispatchQueue` to run `handler` on when the shutdown operation completes.
- /// - handler: The handler which is called after the shutdown operation completes. The parameter will be `nil`
- /// on success and contain the `Error` otherwise.
- public func shutdownGracefully(queue: DispatchQueue, _ handler: @escaping (Error?) -> Void) {
- self._shutdownGracefully(queue: queue, handler)
- }
- #endif
-
+
private func _shutdownGracefully(queue: DispatchQueue, _ handler: @escaping ShutdownGracefullyCallback) {
guard self.canBeShutDown else {
queue.async {
diff --git a/Sources/NIOPosix/NIOThreadPool.swift b/Sources/NIOPosix/NIOThreadPool.swift
index b57c699be..e6b631d1a 100644
--- a/Sources/NIOPosix/NIOThreadPool.swift
+++ b/Sources/NIOPosix/NIOThreadPool.swift
@@ -18,7 +18,7 @@ import NIOConcurrencyHelpers
/// Errors that may be thrown when executing work on a `NIOThreadPool`
public enum NIOThreadPoolError {
-
+
/// The `NIOThreadPool` was not active.
public struct ThreadPoolInactive: Error {
public init() {}
@@ -55,14 +55,9 @@ public final class NIOThreadPool {
/// The `WorkItem` was cancelled and will not be processed by the `NIOThreadPool`.
case cancelled
}
-
- #if swift(>=5.7)
+
/// The work that should be done by the `NIOThreadPool`.
public typealias WorkItem = @Sendable (WorkItemState) -> Void
- #else
- /// The work that should be done by the `NIOThreadPool`.
- public typealias WorkItem = (WorkItemState) -> Void
- #endif
private enum State {
/// The `NIOThreadPool` is already stopped.
case stopped
@@ -78,7 +73,6 @@ public final class NIOThreadPool {
private let numberOfThreads: Int
private let canBeStopped: Bool
- #if swift(>=5.7)
/// Gracefully shutdown this `NIOThreadPool`. All tasks will be run before shutdown will take place.
///
/// - parameters:
@@ -88,17 +82,7 @@ public final class NIOThreadPool {
public func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping @Sendable (Error?) -> Void) {
self._shutdownGracefully(queue: queue, callback)
}
- #else
- /// Gracefully shutdown this `NIOThreadPool`. All tasks will be run before shutdown will take place.
- ///
- /// - parameters:
- /// - queue: The `DispatchQueue` used to executed the callback
- /// - callback: The function to be executed once the shutdown is complete.
- public func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping (Error?) -> Void) {
- self._shutdownGracefully(queue: queue, callback)
- }
- #endif
-
+
private func _shutdownGracefully(queue: DispatchQueue, _ callback: @escaping (Error?) -> Void) {
guard self.canBeStopped else {
queue.async {
@@ -135,10 +119,9 @@ public final class NIOThreadPool {
callback(nil)
}
}
-
-
- #if swift(>=5.7)
+
+
/// Submit a `WorkItem` to process.
///
/// - note: This is a low-level method, in most cases the `runIfActive` method should be used.
@@ -149,17 +132,6 @@ public final class NIOThreadPool {
public func submit(_ body: @escaping WorkItem) {
self._submit(body)
}
- #else
- /// Submit a `WorkItem` to process.
- ///
- /// - note: This is a low-level method, in most cases the `runIfActive` method should be used.
- ///
- /// - parameters:
- /// - body: The `WorkItem` to process by the `NIOThreadPool`.
- public func submit(_ body: @escaping WorkItem) {
- self._submit(body)
- }
- #endif
private func _submit(_ body: @escaping WorkItem) {
let item = self.lock.withLock { () -> WorkItem? in
@@ -176,7 +148,7 @@ public final class NIOThreadPool {
/* if item couldn't be added run it immediately indicating that it couldn't be run */
item.map { $0(.cancelled) }
}
-
+
/// Initialize a `NIOThreadPool` thread pool with `numberOfThreads` threads.
///
/// - parameters:
@@ -290,8 +262,7 @@ public final class NIOThreadPool {
extension NIOThreadPool: @unchecked Sendable {}
extension NIOThreadPool {
-
- #if swift(>=5.7)
+
/// Runs the submitted closure if the thread pool is still active, otherwise fails the promise.
/// The closure will be run on the thread pool so can do blocking work.
///
@@ -303,19 +274,7 @@ extension NIOThreadPool {
public func runIfActive(eventLoop: EventLoop, _ body: @escaping @Sendable () throws -> T) -> EventLoopFuture {
self._runIfActive(eventLoop: eventLoop, body)
}
- #else
- /// Runs the submitted closure if the thread pool is still active, otherwise fails the promise.
- /// The closure will be run on the thread pool so can do blocking work.
- ///
- /// - parameters:
- /// - eventLoop: The `EventLoop` the returned `EventLoopFuture` will fire on.
- /// - body: The closure which performs some blocking work to be done on the thread pool.
- /// - returns: The `EventLoopFuture` of `promise` fulfilled with the result (or error) of the passed closure.
- public func runIfActive(eventLoop: EventLoop, _ body: @escaping () throws -> T) -> EventLoopFuture {
- self._runIfActive(eventLoop: eventLoop, body)
- }
- #endif
-
+
private func _runIfActive(eventLoop: EventLoop, _ body: @escaping () throws -> T) -> EventLoopFuture {
let promise = eventLoop.makePromise(of: T.self)
self.submit { shouldRun in
@@ -334,16 +293,10 @@ extension NIOThreadPool {
}
extension NIOThreadPool {
- #if swift(>=5.7)
@preconcurrency
public func shutdownGracefully(_ callback: @escaping @Sendable (Error?) -> Void) {
self.shutdownGracefully(queue: .global(), callback)
}
- #else
- public func shutdownGracefully(_ callback: @escaping (Error?) -> Void) {
- self.shutdownGracefully(queue: .global(), callback)
- }
- #endif
/// Shuts down the thread pool gracefully.
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
@@ -360,16 +313,10 @@ extension NIOThreadPool {
}
}
- #if swift(>=5.7)
@available(*, noasync, message: "this can end up blocking the calling thread", renamed: "shutdownGracefully()")
public func syncShutdownGracefully() throws {
try self._syncShutdownGracefully()
}
- #else
- public func syncShutdownGracefully() throws {
- try self._syncShutdownGracefully()
- }
- #endif
private func _syncShutdownGracefully() throws {
let errorStorageLock = NIOLock()
diff --git a/Sources/NIOPosix/NonBlockingFileIO.swift b/Sources/NIOPosix/NonBlockingFileIO.swift
index 7fe20193e..64daf5f12 100644
--- a/Sources/NIOPosix/NonBlockingFileIO.swift
+++ b/Sources/NIOPosix/NonBlockingFileIO.swift
@@ -52,8 +52,7 @@ public struct NonBlockingFileIO: Sendable {
public init(threadPool: NIOThreadPool) {
self.threadPool = threadPool
}
-
- #if swift(>=5.7)
+
/// Read a `FileRegion` in chunks of `chunkSize` bytes on `NonBlockingFileIO`'s private thread
/// pool which is separate from any `EventLoop` thread.
///
@@ -89,44 +88,7 @@ public struct NonBlockingFileIO: Sendable {
eventLoop: eventLoop,
chunkHandler: chunkHandler)
}
- #else
- /// Read a `FileRegion` in chunks of `chunkSize` bytes on `NonBlockingFileIO`'s private thread
- /// pool which is separate from any `EventLoop` thread.
- ///
- /// `chunkHandler` will be called on `eventLoop` for every chunk that was read. Assuming `fileRegion.readableBytes` is greater than
- /// zero and there are enough bytes available `chunkHandler` will be called `1 + |_ fileRegion.readableBytes / chunkSize _|`
- /// times, delivering `chunkSize` bytes each time. If less than `fileRegion.readableBytes` bytes can be read from the file,
- /// `chunkHandler` will be called less often with the last invocation possibly being of less than `chunkSize` bytes.
- ///
- /// The allocation and reading of a subsequent chunk will only be attempted when `chunkHandler` succeeds.
- ///
- /// This method will not use the file descriptor's seek pointer which means there is no danger of reading from the
- /// same `FileRegion` in multiple threads.
- ///
- /// - parameters:
- /// - fileRegion: The file region to read.
- /// - chunkSize: The size of the individual chunks to deliver.
- /// - allocator: A `ByteBufferAllocator` used to allocate space for the chunks.
- /// - eventLoop: The `EventLoop` to call `chunkHandler` on.
- /// - chunkHandler: Called for every chunk read. The next chunk will be read upon successful completion of the returned `EventLoopFuture`. If the returned `EventLoopFuture` fails, the overall operation is aborted.
- /// - returns: An `EventLoopFuture` which is the result of the overall operation. If either the reading of `fileHandle` or `chunkHandler` fails, the `EventLoopFuture` will fail too. If the reading of `fileHandle` as well as `chunkHandler` always succeeded, the `EventLoopFuture` will succeed too.
- public func readChunked(fileRegion: FileRegion,
- chunkSize: Int = NonBlockingFileIO.defaultChunkSize,
- allocator: ByteBufferAllocator,
- eventLoop: EventLoop,
- chunkHandler: @escaping (ByteBuffer) -> EventLoopFuture) -> EventLoopFuture {
- let readableBytes = fileRegion.readableBytes
- return self.readChunked(fileHandle: fileRegion.fileHandle,
- fromOffset: Int64(fileRegion.readerIndex),
- byteCount: readableBytes,
- chunkSize: chunkSize,
- allocator: allocator,
- eventLoop: eventLoop,
- chunkHandler: chunkHandler)
- }
- #endif
- #if swift(>=5.7)
/// Read `byteCount` bytes in chunks of `chunkSize` bytes from `fileHandle` in `NonBlockingFileIO`'s private thread
/// pool which is separate from any `EventLoop` thread.
///
@@ -165,47 +127,7 @@ public struct NonBlockingFileIO: Sendable {
eventLoop: eventLoop,
chunkHandler: chunkHandler)
}
- #else
- /// Read `byteCount` bytes in chunks of `chunkSize` bytes from `fileHandle` in `NonBlockingFileIO`'s private thread
- /// pool which is separate from any `EventLoop` thread.
- ///
- /// `chunkHandler` will be called on `eventLoop` for every chunk that was read. Assuming `byteCount` is greater than
- /// zero and there are enough bytes available `chunkHandler` will be called `1 + |_ byteCount / chunkSize _|`
- /// times, delivering `chunkSize` bytes each time. If less than `byteCount` bytes can be read from `descriptor`,
- /// `chunkHandler` will be called less often with the last invocation possibly being of less than `chunkSize` bytes.
- ///
- /// The allocation and reading of a subsequent chunk will only be attempted when `chunkHandler` succeeds.
- ///
- /// - note: `readChunked(fileRegion:chunkSize:allocator:eventLoop:chunkHandler:)` should be preferred as it uses
- /// `FileRegion` object instead of raw `NIOFileHandle`s. In case you do want to use raw `NIOFileHandle`s,
- /// please consider using `readChunked(fileHandle:fromOffset:chunkSize:allocator:eventLoop:chunkHandler:)`
- /// because it doesn't use the file descriptor's seek pointer (which may be shared with other file
- /// descriptors and even across processes.)
- ///
- /// - parameters:
- /// - fileHandle: The `NIOFileHandle` to read from.
- /// - byteCount: The number of bytes to read from `fileHandle`.
- /// - chunkSize: The size of the individual chunks to deliver.
- /// - allocator: A `ByteBufferAllocator` used to allocate space for the chunks.
- /// - eventLoop: The `EventLoop` to call `chunkHandler` on.
- /// - chunkHandler: Called for every chunk read. The next chunk will be read upon successful completion of the returned `EventLoopFuture`. If the returned `EventLoopFuture` fails, the overall operation is aborted.
- /// - returns: An `EventLoopFuture` which is the result of the overall operation. If either the reading of `fileHandle` or `chunkHandler` fails, the `EventLoopFuture` will fail too. If the reading of `fileHandle` as well as `chunkHandler` always succeeded, the `EventLoopFuture` will succeed too.
- public func readChunked(fileHandle: NIOFileHandle,
- byteCount: Int,
- chunkSize: Int = NonBlockingFileIO.defaultChunkSize,
- allocator: ByteBufferAllocator,
- eventLoop: EventLoop, chunkHandler: @escaping (ByteBuffer) -> EventLoopFuture) -> EventLoopFuture {
- return self.readChunked0(fileHandle: fileHandle,
- fromOffset: nil,
- byteCount: byteCount,
- chunkSize: chunkSize,
- allocator: allocator,
- eventLoop: eventLoop,
- chunkHandler: chunkHandler)
- }
- #endif
- #if swift(>=5.7)
/// Read `byteCount` bytes from offset `fileOffset` in chunks of `chunkSize` bytes from `fileHandle` in `NonBlockingFileIO`'s private thread
/// pool which is separate from any `EventLoop` thread.
///
@@ -246,53 +168,8 @@ public struct NonBlockingFileIO: Sendable {
eventLoop: eventLoop,
chunkHandler: chunkHandler)
}
- #else
- /// Read `byteCount` bytes from offset `fileOffset` in chunks of `chunkSize` bytes from `fileHandle` in `NonBlockingFileIO`'s private thread
- /// pool which is separate from any `EventLoop` thread.
- ///
- /// `chunkHandler` will be called on `eventLoop` for every chunk that was read. Assuming `byteCount` is greater than
- /// zero and there are enough bytes available `chunkHandler` will be called `1 + |_ byteCount / chunkSize _|`
- /// times, delivering `chunkSize` bytes each time. If less than `byteCount` bytes can be read from `descriptor`,
- /// `chunkHandler` will be called less often with the last invocation possibly being of less than `chunkSize` bytes.
- ///
- /// The allocation and reading of a subsequent chunk will only be attempted when `chunkHandler` succeeds.
- ///
- /// This method will not use the file descriptor's seek pointer which means there is no danger of reading from the
- /// same `NIOFileHandle` in multiple threads.
- ///
- /// - note: `readChunked(fileRegion:chunkSize:allocator:eventLoop:chunkHandler:)` should be preferred as it uses
- /// `FileRegion` object instead of raw `NIOFileHandle`s.
- ///
- /// - parameters:
- /// - fileHandle: The `NIOFileHandle` to read from.
- /// - byteCount: The number of bytes to read from `fileHandle`.
- /// - chunkSize: The size of the individual chunks to deliver.
- /// - allocator: A `ByteBufferAllocator` used to allocate space for the chunks.
- /// - eventLoop: The `EventLoop` to call `chunkHandler` on.
- /// - chunkHandler: Called for every chunk read. The next chunk will be read upon successful completion of the returned `EventLoopFuture`. If the returned `EventLoopFuture` fails, the overall operation is aborted.
- /// - returns: An `EventLoopFuture` which is the result of the overall operation. If either the reading of `fileHandle` or `chunkHandler` fails, the `EventLoopFuture` will fail too. If the reading of `fileHandle` as well as `chunkHandler` always succeeded, the `EventLoopFuture` will succeed too.
- public func readChunked(fileHandle: NIOFileHandle,
- fromOffset fileOffset: Int64,
- byteCount: Int,
- chunkSize: Int = NonBlockingFileIO.defaultChunkSize,
- allocator: ByteBufferAllocator,
- eventLoop: EventLoop,
- chunkHandler: @escaping (ByteBuffer) -> EventLoopFuture) -> EventLoopFuture {
- return self.readChunked0(fileHandle: fileHandle,
- fromOffset: fileOffset,
- byteCount: byteCount,
- chunkSize: chunkSize,
- allocator: allocator,
- eventLoop: eventLoop,
- chunkHandler: chunkHandler)
- }
- #endif
-
- #if swift(>=5.7)
+
private typealias ReadChunkHandler = @Sendable (ByteBuffer) -> EventLoopFuture
- #else
- private typealias ReadChunkHandler = (ByteBuffer) -> EventLoopFuture
- #endif
private func readChunked0(fileHandle: NIOFileHandle,
fromOffset: Int64?,
@@ -303,7 +180,7 @@ public struct NonBlockingFileIO: Sendable {
precondition(chunkSize > 0, "chunkSize must be > 0 (is \(chunkSize))")
let remainingReads = 1 + (byteCount / chunkSize)
let lastReadSize = byteCount % chunkSize
-
+
let promise = eventLoop.makePromise(of: Void.self)
func _read(remainingReads: Int, bytesReadSoFar: Int64) {
diff --git a/Sources/NIOPosix/Thread.swift b/Sources/NIOPosix/Thread.swift
index be392dec4..68b486c72 100644
--- a/Sources/NIOPosix/Thread.swift
+++ b/Sources/NIOPosix/Thread.swift
@@ -17,7 +17,7 @@ import CNIOLinux
#endif
enum LowLevelThreadOperations {
-
+
}
protocol ThreadOps {
@@ -185,8 +185,7 @@ public final class ThreadSpecificVariable {
self.currentValue = value
}
-
- #if swift(>=5.7)
+
/// The value for the current thread.
@available(*, noasync, message: "threads can change between suspension points and therefore the thread specific value too")
public var currentValue: Value? {
@@ -197,18 +196,7 @@ public final class ThreadSpecificVariable {
self.set(newValue)
}
}
- #else
- /// The value for the current thread.
- public var currentValue: Value? {
- get {
- self.get()
- }
- set {
- self.set(newValue)
- }
- }
- #endif
-
+
/// Get the current value for the calling thread.
func get() -> Value? {
guard let raw = self.key.get() else { return nil }
@@ -218,7 +206,7 @@ public final class ThreadSpecificVariable {
.takeUnretainedValue()
.value.1 as! Value)
}
-
+
/// Set the current value for the calling threads. The `currentValue` for all other threads remains unchanged.
func set(_ newValue: Value?) {
if let raw = self.key.get() {
diff --git a/Sources/NIOWebSocket/NIOWebSocketServerUpgrader.swift b/Sources/NIOWebSocket/NIOWebSocketServerUpgrader.swift
index 4d1f77f6a..9a245edbb 100644
--- a/Sources/NIOWebSocket/NIOWebSocketServerUpgrader.swift
+++ b/Sources/NIOWebSocket/NIOWebSocketServerUpgrader.swift
@@ -64,15 +64,10 @@ fileprivate extension HTTPHeaders {
public final class NIOWebSocketServerUpgrader: HTTPServerProtocolUpgrader, @unchecked Sendable {
// This type *is* Sendable but we can't express that properly until Swift 5.7. In the meantime
// the conformance is `@unchecked`.
-
- #if swift(>=5.7)
+
// FIXME: remove @unchecked when 5.7 is the minimum supported version.
private typealias ShouldUpgrade = @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture
private typealias UpgradePipelineHandler = @Sendable (Channel, HTTPRequestHead) -> EventLoopFuture
- #else
- private typealias ShouldUpgrade = (Channel, HTTPRequestHead) -> EventLoopFuture
- private typealias UpgradePipelineHandler = (Channel, HTTPRequestHead) -> EventLoopFuture
- #endif
/// RFC 6455 specs this as the required entry in the Upgrade header.
public let supportedProtocol: String = "websocket"
@@ -86,7 +81,6 @@ public final class NIOWebSocketServerUpgrader: HTTPServerProtocolUpgrader, @unch
private let maxFrameSize: Int
private let automaticErrorHandling: Bool
- #if swift(>=5.7)
/// Create a new `NIOWebSocketServerUpgrader`.
///
/// - parameters:
@@ -112,34 +106,7 @@ public final class NIOWebSocketServerUpgrader: HTTPServerProtocolUpgrader, @unch
self.init(maxFrameSize: 1 << 14, automaticErrorHandling: automaticErrorHandling,
shouldUpgrade: shouldUpgrade, upgradePipelineHandler: upgradePipelineHandler)
}
- #else
- /// Create a new `NIOWebSocketServerUpgrader`.
- ///
- /// - parameters:
- /// - automaticErrorHandling: Whether the pipeline should automatically handle protocol
- /// errors by sending error responses and closing the connection. Defaults to `true`,
- /// may be set to `false` if the user wishes to handle their own errors.
- /// - shouldUpgrade: A callback that determines whether the websocket request should be
- /// upgraded. This callback is responsible for creating a `HTTPHeaders` object with
- /// any headers that it needs on the response *except for* the `Upgrade`, `Connection`,
- /// and `Sec-WebSocket-Accept` headers, which this upgrader will handle. Should return
- /// an `EventLoopFuture` containing `nil` if the upgrade should be refused.
- /// - upgradePipelineHandler: A function that will be called once the upgrade response is
- /// flushed, and that is expected to mutate the `Channel` appropriately to handle the
- /// websocket protocol. This only needs to add the user handlers: the
- /// `WebSocketFrameEncoder` and `WebSocketFrameDecoder` will have been added to the
- /// pipeline automatically.
- public convenience init(
- automaticErrorHandling: Bool = true,
- shouldUpgrade: @escaping (Channel, HTTPRequestHead) -> EventLoopFuture,
- upgradePipelineHandler: @escaping (Channel, HTTPRequestHead) -> EventLoopFuture
- ) {
- self.init(maxFrameSize: 1 << 14, automaticErrorHandling: automaticErrorHandling,
- shouldUpgrade: shouldUpgrade, upgradePipelineHandler: upgradePipelineHandler)
- }
- #endif
- #if swift(>=5.7)
/// Create a new `NIOWebSocketServerUpgrader`.
///
/// - parameters:
@@ -174,42 +141,7 @@ public final class NIOWebSocketServerUpgrader: HTTPServerProtocolUpgrader, @unch
upgradePipelineHandler: upgradePipelineHandler
)
}
- #else
- /// Create a new `NIOWebSocketServerUpgrader`.
- ///
- /// - parameters:
- /// - maxFrameSize: The maximum frame size the decoder is willing to tolerate from the
- /// remote peer. WebSockets in principle allows frame sizes up to `2**64` bytes, but
- /// this is an objectively unreasonable maximum value (on AMD64 systems it is not
- /// possible to even. Users may set this to any value up to `UInt32.max`.
- /// - automaticErrorHandling: Whether the pipeline should automatically handle protocol
- /// errors by sending error responses and closing the connection. Defaults to `true`,
- /// may be set to `false` if the user wishes to handle their own errors.
- /// - shouldUpgrade: A callback that determines whether the websocket request should be
- /// upgraded. This callback is responsible for creating a `HTTPHeaders` object with
- /// any headers that it needs on the response *except for* the `Upgrade`, `Connection`,
- /// and `Sec-WebSocket-Accept` headers, which this upgrader will handle. Should return
- /// an `EventLoopFuture` containing `nil` if the upgrade should be refused.
- /// - upgradePipelineHandler: A function that will be called once the upgrade response is
- /// flushed, and that is expected to mutate the `Channel` appropriately to handle the
- /// websocket protocol. This only needs to add the user handlers: the
- /// `WebSocketFrameEncoder` and `WebSocketFrameDecoder` will have been added to the
- /// pipeline automatically.
- public convenience init(
- maxFrameSize: Int,
- automaticErrorHandling: Bool = true,
- shouldUpgrade: @escaping (Channel, HTTPRequestHead) -> EventLoopFuture,
- upgradePipelineHandler: @escaping (Channel, HTTPRequestHead) -> EventLoopFuture
- ) {
- self.init(
- _maxFrameSize: maxFrameSize,
- automaticErrorHandling: automaticErrorHandling,
- shouldUpgrade: shouldUpgrade,
- upgradePipelineHandler: upgradePipelineHandler
- )
- }
- #endif
-
+
private init(
_maxFrameSize maxFrameSize: Int,
automaticErrorHandling: Bool,
diff --git a/Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift b/Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift
index d9821d6a5..4f0fdc64e 100644
--- a/Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift
+++ b/Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift
@@ -83,11 +83,7 @@ extension EmbeddedChannel {
}
}
-#if swift(>=5.7)
private typealias UpgradeCompletionHandler = @Sendable (ChannelHandlerContext) -> Void
-#else
-private typealias UpgradeCompletionHandler = (ChannelHandlerContext) -> Void
-#endif
private func serverHTTPChannelWithAutoremoval(group: EventLoopGroup,
pipelining: Bool,
diff --git a/docker/docker-compose.2004.56.yaml b/docker/docker-compose.2204.510.yaml
similarity index 71%
rename from docker/docker-compose.2004.56.yaml
rename to docker/docker-compose.2204.510.yaml
index f26cac2fe..ef1732e29 100644
--- a/docker/docker-compose.2004.56.yaml
+++ b/docker/docker-compose.2204.510.yaml
@@ -3,28 +3,27 @@ version: "3"
services:
runtime-setup:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
build:
args:
- ubuntu_version: "focal"
- swift_version: "5.6"
+ base_image: "swiftlang/swift:nightly-5.10-jammy"
unit-tests:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
integration-tests:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
documentation-check:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
test:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
environment:
- - MAX_ALLOCS_ALLOWED_10000000_asyncsequenceproducer=22
+ - MAX_ALLOCS_ALLOWED_10000000_asyncsequenceproducer=21
- MAX_ALLOCS_ALLOWED_1000000_asyncwriter=1000050
- MAX_ALLOCS_ALLOWED_1000_addHandlers=45050
- - MAX_ALLOCS_ALLOWED_1000_addHandlers_sync=39050
+ - MAX_ALLOCS_ALLOWED_1000_addHandlers_sync=38050
- MAX_ALLOCS_ALLOWED_1000_addRemoveHandlers_handlercontext=8050
- MAX_ALLOCS_ALLOWED_1000_addRemoveHandlers_handlername=8050
- MAX_ALLOCS_ALLOWED_1000_addRemoveHandlers_handlertype=8050
@@ -35,13 +34,13 @@ services:
- MAX_ALLOCS_ALLOWED_1000_getHandlers=8050
- MAX_ALLOCS_ALLOWED_1000_getHandlers_sync=36
- MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=26400
- - MAX_ALLOCS_ALLOWED_1000_rst_connections=151050
- - MAX_ALLOCS_ALLOWED_1000_tcpbootstraps=4050
- - MAX_ALLOCS_ALLOWED_1000_tcpconnections=156050
+ - MAX_ALLOCS_ALLOWED_1000_rst_connections=149050
+ - MAX_ALLOCS_ALLOWED_1000_tcpbootstraps=3050
+ - MAX_ALLOCS_ALLOWED_1000_tcpconnections=157050
- MAX_ALLOCS_ALLOWED_1000_udp_reqs=6050
- MAX_ALLOCS_ALLOWED_1000_udpbootstraps=2050
- MAX_ALLOCS_ALLOWED_1000_udpconnections=77050
- - MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=404000
+ - MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=396000
- MAX_ALLOCS_ALLOWED_bytebuffer_lots_of_rw=2050
- MAX_ALLOCS_ALLOWED_creating_10000_headers=0
- MAX_ALLOCS_ALLOWED_decode_1000_ws_frames=2050
@@ -61,26 +60,27 @@ services:
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace_from_long_string=700050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace_from_short_string=700050
- MAX_ALLOCS_ALLOWED_modifying_1000_circular_buffer_elements=0
- - MAX_ALLOCS_ALLOWED_modifying_byte_buffer_view=2050
- - MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=339
+ - MAX_ALLOCS_ALLOWED_modifying_byte_buffer_view=6050
+ - MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=343
- MAX_ALLOCS_ALLOWED_read_10000_chunks_from_file=140050
- - MAX_ALLOCS_ALLOWED_schedule_10000_tasks=60100
- - MAX_ALLOCS_ALLOWED_schedule_and_run_10000_tasks=60050
- - MAX_ALLOCS_ALLOWED_scheduling_10000_executions=86
+ - MAX_ALLOCS_ALLOWED_schedule_10000_tasks=50100
+ - MAX_ALLOCS_ALLOWED_schedule_and_run_10000_tasks=50050
+ - MAX_ALLOCS_ALLOWED_scheduling_10000_executions=85
- MAX_ALLOCS_ALLOWED_udp_1000_reqs_1_conn=6200
- - MAX_ALLOCS_ALLOWED_udp_1_reqs_1000_conn=161050
+ - MAX_ALLOCS_ALLOWED_udp_1_reqs_1000_conn=167050
- FORCE_TEST_DISCOVERY=--enable-test-discovery
- WARN_AS_ERROR_ARG=-Xswiftc -warnings-as-errors
+ - IMPORT_CHECK_ARG=--explicit-target-dependency-import-check error
# - SANITIZER_ARG=--sanitize=thread # TSan broken still
performance-test:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
shell:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
echo:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
http:
- image: swift-nio:20.04-5.6
+ image: swift-nio:22.04-5.10
diff --git a/docker/docker-compose.2204.59.yaml b/docker/docker-compose.2204.59.yaml
index baf70a967..357536253 100644
--- a/docker/docker-compose.2204.59.yaml
+++ b/docker/docker-compose.2204.59.yaml
@@ -6,7 +6,8 @@ services:
image: swift-nio:22.04-5.9
build:
args:
- base_image: "swiftlang/swift:nightly-5.9-jammy"
+ ubuntu_version: "jammy"
+ swift_version: "5.9"
unit-tests:
image: swift-nio:22.04-5.9