From 63dc377656035dc620c0896a421f6f33c140cbd5 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Fri, 30 May 2025 07:43:57 +0100 Subject: [PATCH 1/5] Adjust for SendableMetatype Motivation With the introduction of isolated conformances, it has become necessary to start managing the use of metatypes for some of our protocols. In general, we don't want to force the relevant protocols to only be conformed in non-isolated forms. Instead, we just want to make the specific APIs non-usable. Modifications - Add shims for SendableMetatype that only use it when it is available. - Require SendableMetatype where needed, gated by @preconcurrency. Result We continue to be safe. --- Sources/NIOCore/AsyncAwaitSupport.swift | 3 ++- Sources/NIOCore/ChannelPipeline.swift | 9 ++++++--- Sources/NIOCore/NIOCoreSendableMetatype.swift | 19 +++++++++++++++++++ Sources/NIOFileSystem/DirectoryEntries.swift | 4 ++-- Sources/NIOFileSystem/FileChunks.swift | 3 ++- .../Internal/BufferedOrAnyStream.swift | 6 +++--- .../NIOFileSystemSendableMetatype.swift | 19 +++++++++++++++++++ .../NIOPosix/NIOPosixSendableMetatype.swift | 19 +++++++++++++++++++ Sources/NIOPosix/SocketProtocols.swift | 2 +- .../NIOWebSocketClientUpgrader.swift | 3 --- .../HTTPServerUpgradeTests.swift | 4 ++-- 11 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 Sources/NIOCore/NIOCoreSendableMetatype.swift create mode 100644 Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift create mode 100644 Sources/NIOPosix/NIOPosixSendableMetatype.swift diff --git a/Sources/NIOCore/AsyncAwaitSupport.swift b/Sources/NIOCore/AsyncAwaitSupport.swift index ba8dfa3cf6e..c7effad899d 100644 --- a/Sources/NIOCore/AsyncAwaitSupport.swift +++ b/Sources/NIOCore/AsyncAwaitSupport.swift @@ -280,7 +280,8 @@ extension ChannelPipeline { "ChannelHandlerContext is not Sendable and it is therefore not safe to be used outside of its EventLoop" ) @inlinable - public func context(handlerType: Handler.Type) async throws -> ChannelHandlerContext { + @preconcurrency + public func context(handlerType: Handler.Type) async throws -> ChannelHandlerContext { try await self.context(handlerType: handlerType).map { UnsafeTransfer($0) }.get().wrappedValue } diff --git a/Sources/NIOCore/ChannelPipeline.swift b/Sources/NIOCore/ChannelPipeline.swift index 6b63c5e2bb6..cd6fea40142 100644 --- a/Sources/NIOCore/ChannelPipeline.swift +++ b/Sources/NIOCore/ChannelPipeline.swift @@ -534,7 +534,8 @@ public final class ChannelPipeline: ChannelInvoker { /// - handlerType: The type of the handler to search for. /// - Returns: the `EventLoopFuture` which will be notified once the the operation completes. @inlinable - public func context(handlerType: Handler.Type) -> EventLoopFuture { + @preconcurrency + public func context(handlerType: Handler.Type) -> EventLoopFuture { let promise = self.eventLoop.makePromise(of: ChannelHandlerContext.self) if self.eventLoop.inEventLoop { @@ -555,7 +556,8 @@ public final class ChannelPipeline: ChannelInvoker { /// - Returns: An ``EventLoopFuture`` that is succeeded if a handler of the given type is contained in the pipeline. Otherwise /// the future will be failed with an error. @inlinable - public func containsHandler(type: Handler.Type) -> EventLoopFuture { + @preconcurrency + public func containsHandler(type: Handler.Type) -> EventLoopFuture { self.handler(type: type).map { _ in () } } @@ -2424,7 +2426,8 @@ extension ChannelPipeline: CustomDebugStringConvertible { /// - Parameters: /// - type: the type of `ChannelHandler` to return. @inlinable - public func handler(type _: Handler.Type) -> EventLoopFuture { + @preconcurrency + public func handler(type _: Handler.Type) -> EventLoopFuture { self.context(handlerType: Handler.self).map { context in guard let typedContext = context.handler as? Handler else { preconditionFailure( diff --git a/Sources/NIOCore/NIOCoreSendableMetatype.swift b/Sources/NIOCore/NIOCoreSendableMetatype.swift new file mode 100644 index 00000000000..f8c7c86d868 --- /dev/null +++ b/Sources/NIOCore/NIOCoreSendableMetatype.swift @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if compiler(>=6.2) +public typealias _NIOCoreSendableMetatype = SendableMetatype +#else +public typealias _NIOCoreSendableMetatype = Any +#endif \ No newline at end of file diff --git a/Sources/NIOFileSystem/DirectoryEntries.swift b/Sources/NIOFileSystem/DirectoryEntries.swift index 1c0fa9d0b71..80950a45181 100644 --- a/Sources/NIOFileSystem/DirectoryEntries.swift +++ b/Sources/NIOFileSystem/DirectoryEntries.swift @@ -36,7 +36,7 @@ public struct DirectoryEntries: AsyncSequence, Sendable { /// Creates a ``DirectoryEntries`` sequence by wrapping an `AsyncSequence` of _batches_ of /// directory entries. @preconcurrency - public init(wrapping sequence: S) where S.Element == Batched.Element { + public init(wrapping sequence: S) where S.Element == Batched.Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { self.batchedSequence = Batched(wrapping: sequence) } @@ -95,7 +95,7 @@ extension DirectoryEntries { /// Creates a ``DirectoryEntries/Batched`` sequence by wrapping an `AsyncSequence` /// of directory entry batches. @preconcurrency - public init(wrapping sequence: S) where S.Element == Element { + public init(wrapping sequence: S) where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { self.stream = BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>(wrapping: sequence) } diff --git a/Sources/NIOFileSystem/FileChunks.swift b/Sources/NIOFileSystem/FileChunks.swift index 00338236b05..81320ce29f0 100644 --- a/Sources/NIOFileSystem/FileChunks.swift +++ b/Sources/NIOFileSystem/FileChunks.swift @@ -31,7 +31,8 @@ public struct FileChunks: AsyncSequence, Sendable { private let stream: BufferedOrAnyStream /// Create a ``FileChunks`` sequence backed by wrapping an `AsyncSequence`. - public init(wrapping sequence: S) where S.Element == ByteBuffer { + @preconcurrency + public init(wrapping sequence: S) where S.Element == ByteBuffer, S.AsyncIterator: _NIOFileSystemSendableMetatype { self.stream = BufferedOrAnyStream(wrapping: sequence) } diff --git a/Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift b/Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift index 50e097b931e..327f4b411f3 100644 --- a/Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift +++ b/Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift @@ -28,7 +28,7 @@ internal enum BufferedOrAnyStream(wrapping stream: S) where S.Element == Element { + internal init(wrapping stream: S) where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { self = .anyAsyncSequence(AnyAsyncSequence(wrapping: stream)) } @@ -72,7 +72,7 @@ internal enum BufferedOrAnyStream: AsyncSequence, Sendable { private let _makeAsyncIterator: @Sendable () -> AsyncIterator - internal init(wrapping sequence: S) where S.Element == Element { + internal init(wrapping sequence: S) where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { self._makeAsyncIterator = { AsyncIterator(wrapping: sequence.makeAsyncIterator()) } @@ -82,7 +82,7 @@ internal struct AnyAsyncSequence: AsyncSequence, Sendable { self._makeAsyncIterator() } - internal struct AsyncIterator: AsyncIteratorProtocol { + internal struct AsyncIterator: AsyncIteratorProtocol, _NIOFileSystemSendableMetatype { private var iterator: any AsyncIteratorProtocol init(wrapping iterator: I) where I.Element == Element { diff --git a/Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift b/Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift new file mode 100644 index 00000000000..8b72406f556 --- /dev/null +++ b/Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if compiler(>=6.2) +public typealias _NIOFileSystemSendableMetatype = SendableMetatype +#else +public typealias _NIOFileSystemSendableMetatype = Any +#endif \ No newline at end of file diff --git a/Sources/NIOPosix/NIOPosixSendableMetatype.swift b/Sources/NIOPosix/NIOPosixSendableMetatype.swift new file mode 100644 index 00000000000..6f1ce1a0728 --- /dev/null +++ b/Sources/NIOPosix/NIOPosixSendableMetatype.swift @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if compiler(>=6.2) +public typealias _NIOPosixSendableMetatype = SendableMetatype +#else +public typealias _NIOPosixSendableMetatype = Any +#endif \ No newline at end of file diff --git a/Sources/NIOPosix/SocketProtocols.swift b/Sources/NIOPosix/SocketProtocols.swift index b376a02be1b..7f3feba1e87 100644 --- a/Sources/NIOPosix/SocketProtocols.swift +++ b/Sources/NIOPosix/SocketProtocols.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import NIOCore -protocol BaseSocketProtocol: CustomStringConvertible { +protocol BaseSocketProtocol: CustomStringConvertible, _NIOPosixSendableMetatype { associatedtype SelectableType: Selectable var isOpen: Bool { get } diff --git a/Sources/NIOWebSocket/NIOWebSocketClientUpgrader.swift b/Sources/NIOWebSocket/NIOWebSocketClientUpgrader.swift index d3aba88b4c5..65a21db4886 100644 --- a/Sources/NIOWebSocket/NIOWebSocketClientUpgrader.swift +++ b/Sources/NIOWebSocket/NIOWebSocketClientUpgrader.swift @@ -129,9 +129,6 @@ public final class NIOTypedWebSocketClientUpgrader: NIO } } -@available(*, unavailable) -extension NIOWebSocketClientUpgrader: Sendable {} - extension NIOWebSocketClientUpgrader { /// Generates a random WebSocket Request Key by generating 16 bytes randomly and encoding them as a base64 string as defined in RFC6455 https://tools.ietf.org/html/rfc6455#section-4.1 /// - Parameter generator: the `RandomNumberGenerator` used as a the source of randomness diff --git a/Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift b/Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift index bc8d58ab348..4e4c84e9d05 100644 --- a/Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift +++ b/Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift @@ -25,7 +25,7 @@ extension ChannelPipeline { try self.assertDoesNotContain(handlerType: HTTPServerUpgradeHandler.self) } - func assertDoesNotContain( + func assertDoesNotContain( handlerType: Handler.Type, file: StaticString = #filePath, line: UInt = #line @@ -49,7 +49,7 @@ extension ChannelPipeline { } } - func assertContains(handlerType: Handler.Type) { + func assertContains(handlerType: Handler.Type) { XCTAssertNoThrow(try self.containsHandler(type: handlerType).wait(), "did not find handler") } From d30b28a0f62c6a718300b8d71be13b3be7f3c502 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Wed, 11 Jun 2025 14:21:26 +0100 Subject: [PATCH 2/5] Formatter --- Sources/NIOCore/AsyncAwaitSupport.swift | 4 +++- Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift | 8 ++++---- Sources/NIOCore/ChannelPipeline.swift | 12 +++++++++--- Sources/NIOCore/NIOCoreSendableMetatype.swift | 2 +- Sources/NIOFileSystem/DirectoryEntries.swift | 6 ++++-- Sources/NIOFileSystem/FileChunks.swift | 3 ++- .../NIOFileSystem/Internal/BufferedOrAnyStream.swift | 6 ++++-- .../NIOFileSystemSendableMetatype.swift | 2 +- Sources/NIOPosix/NIOPosixSendableMetatype.swift | 2 +- 9 files changed, 29 insertions(+), 16 deletions(-) diff --git a/Sources/NIOCore/AsyncAwaitSupport.swift b/Sources/NIOCore/AsyncAwaitSupport.swift index c7effad899d..bd49ac1b67f 100644 --- a/Sources/NIOCore/AsyncAwaitSupport.swift +++ b/Sources/NIOCore/AsyncAwaitSupport.swift @@ -281,7 +281,9 @@ extension ChannelPipeline { ) @inlinable @preconcurrency - public func context(handlerType: Handler.Type) async throws -> ChannelHandlerContext { + public func context( + handlerType: Handler.Type + ) async throws -> ChannelHandlerContext { try await self.context(handlerType: handlerType).map { UnsafeTransfer($0) }.get().wrappedValue } diff --git a/Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift b/Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift index f232d518f96..1a779bbcaaf 100644 --- a/Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift +++ b/Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift @@ -510,7 +510,7 @@ extension NIOAsyncWriter { switch action { case .resumeContinuations(let suspendedYields): for yield in suspendedYields { - yield .continuation.resume(returning: .retry) + yield.continuation.resume(returning: .retry) } case .none: @@ -675,7 +675,7 @@ extension NIOAsyncWriter { case .resumeContinuations(let suspendedYields): for yield in suspendedYields { - yield .continuation.resume(returning: .retry) + yield.continuation.resume(returning: .retry) } case .none: @@ -695,7 +695,7 @@ extension NIOAsyncWriter { switch action { case .resumeContinuationsWithError(let suspendedYields, let error): for yield in suspendedYields { - yield .continuation.resume(throwing: error) + yield.continuation.resume(throwing: error) } case .none: @@ -712,7 +712,7 @@ extension NIOAsyncWriter { case .resumeContinuations(let suspendedYields): for yield in suspendedYields { - yield .continuation.resume(returning: .retry) + yield.continuation.resume(returning: .retry) } return } diff --git a/Sources/NIOCore/ChannelPipeline.swift b/Sources/NIOCore/ChannelPipeline.swift index cd6fea40142..d53f7eb00b0 100644 --- a/Sources/NIOCore/ChannelPipeline.swift +++ b/Sources/NIOCore/ChannelPipeline.swift @@ -535,7 +535,9 @@ public final class ChannelPipeline: ChannelInvoker { /// - Returns: the `EventLoopFuture` which will be notified once the the operation completes. @inlinable @preconcurrency - public func context(handlerType: Handler.Type) -> EventLoopFuture { + public func context( + handlerType: Handler.Type + ) -> EventLoopFuture { let promise = self.eventLoop.makePromise(of: ChannelHandlerContext.self) if self.eventLoop.inEventLoop { @@ -557,7 +559,9 @@ public final class ChannelPipeline: ChannelInvoker { /// the future will be failed with an error. @inlinable @preconcurrency - public func containsHandler(type: Handler.Type) -> EventLoopFuture { + public func containsHandler( + type: Handler.Type + ) -> EventLoopFuture { self.handler(type: type).map { _ in () } } @@ -2427,7 +2431,9 @@ extension ChannelPipeline: CustomDebugStringConvertible { /// - type: the type of `ChannelHandler` to return. @inlinable @preconcurrency - public func handler(type _: Handler.Type) -> EventLoopFuture { + public func handler( + type _: Handler.Type + ) -> EventLoopFuture { self.context(handlerType: Handler.self).map { context in guard let typedContext = context.handler as? Handler else { preconditionFailure( diff --git a/Sources/NIOCore/NIOCoreSendableMetatype.swift b/Sources/NIOCore/NIOCoreSendableMetatype.swift index f8c7c86d868..10bd769c7ca 100644 --- a/Sources/NIOCore/NIOCoreSendableMetatype.swift +++ b/Sources/NIOCore/NIOCoreSendableMetatype.swift @@ -16,4 +16,4 @@ public typealias _NIOCoreSendableMetatype = SendableMetatype #else public typealias _NIOCoreSendableMetatype = Any -#endif \ No newline at end of file +#endif diff --git a/Sources/NIOFileSystem/DirectoryEntries.swift b/Sources/NIOFileSystem/DirectoryEntries.swift index 80950a45181..409d7362f86 100644 --- a/Sources/NIOFileSystem/DirectoryEntries.swift +++ b/Sources/NIOFileSystem/DirectoryEntries.swift @@ -36,7 +36,8 @@ public struct DirectoryEntries: AsyncSequence, Sendable { /// Creates a ``DirectoryEntries`` sequence by wrapping an `AsyncSequence` of _batches_ of /// directory entries. @preconcurrency - public init(wrapping sequence: S) where S.Element == Batched.Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { + public init(wrapping sequence: S) + where S.Element == Batched.Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { self.batchedSequence = Batched(wrapping: sequence) } @@ -95,7 +96,8 @@ extension DirectoryEntries { /// Creates a ``DirectoryEntries/Batched`` sequence by wrapping an `AsyncSequence` /// of directory entry batches. @preconcurrency - public init(wrapping sequence: S) where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { + public init(wrapping sequence: S) + where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { self.stream = BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>(wrapping: sequence) } diff --git a/Sources/NIOFileSystem/FileChunks.swift b/Sources/NIOFileSystem/FileChunks.swift index 81320ce29f0..50f09486e73 100644 --- a/Sources/NIOFileSystem/FileChunks.swift +++ b/Sources/NIOFileSystem/FileChunks.swift @@ -32,7 +32,8 @@ public struct FileChunks: AsyncSequence, Sendable { /// Create a ``FileChunks`` sequence backed by wrapping an `AsyncSequence`. @preconcurrency - public init(wrapping sequence: S) where S.Element == ByteBuffer, S.AsyncIterator: _NIOFileSystemSendableMetatype { + public init(wrapping sequence: S) + where S.Element == ByteBuffer, S.AsyncIterator: _NIOFileSystemSendableMetatype { self.stream = BufferedOrAnyStream(wrapping: sequence) } diff --git a/Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift b/Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift index 327f4b411f3..7e307a16023 100644 --- a/Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift +++ b/Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift @@ -28,7 +28,8 @@ internal enum BufferedOrAnyStream(wrapping stream: S) where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { + internal init(wrapping stream: S) + where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { self = .anyAsyncSequence(AnyAsyncSequence(wrapping: stream)) } @@ -72,7 +73,8 @@ internal enum BufferedOrAnyStream: AsyncSequence, Sendable { private let _makeAsyncIterator: @Sendable () -> AsyncIterator - internal init(wrapping sequence: S) where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { + internal init(wrapping sequence: S) + where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype { self._makeAsyncIterator = { AsyncIterator(wrapping: sequence.makeAsyncIterator()) } diff --git a/Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift b/Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift index 8b72406f556..226cb70cdce 100644 --- a/Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift +++ b/Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift @@ -16,4 +16,4 @@ public typealias _NIOFileSystemSendableMetatype = SendableMetatype #else public typealias _NIOFileSystemSendableMetatype = Any -#endif \ No newline at end of file +#endif diff --git a/Sources/NIOPosix/NIOPosixSendableMetatype.swift b/Sources/NIOPosix/NIOPosixSendableMetatype.swift index 6f1ce1a0728..184932d44cc 100644 --- a/Sources/NIOPosix/NIOPosixSendableMetatype.swift +++ b/Sources/NIOPosix/NIOPosixSendableMetatype.swift @@ -16,4 +16,4 @@ public typealias _NIOPosixSendableMetatype = SendableMetatype #else public typealias _NIOPosixSendableMetatype = Any -#endif \ No newline at end of file +#endif From 52eb3e4b1df3f17da5e052857c290327707b1564 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Wed, 11 Jun 2025 14:24:41 +0100 Subject: [PATCH 3/5] 6.2 formatter changed its mind, apparently --- Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift b/Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift index 1a779bbcaaf..f232d518f96 100644 --- a/Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift +++ b/Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift @@ -510,7 +510,7 @@ extension NIOAsyncWriter { switch action { case .resumeContinuations(let suspendedYields): for yield in suspendedYields { - yield.continuation.resume(returning: .retry) + yield .continuation.resume(returning: .retry) } case .none: @@ -675,7 +675,7 @@ extension NIOAsyncWriter { case .resumeContinuations(let suspendedYields): for yield in suspendedYields { - yield.continuation.resume(returning: .retry) + yield .continuation.resume(returning: .retry) } case .none: @@ -695,7 +695,7 @@ extension NIOAsyncWriter { switch action { case .resumeContinuationsWithError(let suspendedYields, let error): for yield in suspendedYields { - yield.continuation.resume(throwing: error) + yield .continuation.resume(throwing: error) } case .none: @@ -712,7 +712,7 @@ extension NIOAsyncWriter { case .resumeContinuations(let suspendedYields): for yield in suspendedYields { - yield.continuation.resume(returning: .retry) + yield .continuation.resume(returning: .retry) } return } From 64b8be7469cee23d31c661e60f745b602d5a376f Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Thu, 12 Jun 2025 16:30:15 +0100 Subject: [PATCH 4/5] Benchmark number go down --- .../nightly-next/NIOPosixBenchmarks.TCPEcho.p90.json | 2 +- .../NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEcho.p90.json b/Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEcho.p90.json index c6a93680d0a..e1c0a531662 100644 --- a/Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEcho.p90.json +++ b/Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEcho.p90.json @@ -1,3 +1,3 @@ { - "mallocCountTotal" : 108 + "mallocCountTotal": 108 } diff --git a/Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json b/Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json index 390ed2415a7..d714da6722b 100644 --- a/Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json +++ b/Benchmarks/Thresholds/nightly-next/NIOPosixBenchmarks.TCPEchoAsyncChannel.p90.json @@ -1,3 +1,3 @@ { - "mallocCountTotal" : 164376 -} \ No newline at end of file + "mallocCountTotal": 82500 +} From 7fa7b29382e00cab609ee9490c3c3000b70de109 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Thu, 12 Jun 2025 16:46:17 +0100 Subject: [PATCH 5/5] Clean up integration test thresholds --- .../Thresholds/nightly-main.json | 28 +++++++-------- .../Thresholds/nightly-next.json | 36 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/IntegrationTests/tests_04_performance/Thresholds/nightly-main.json b/IntegrationTests/tests_04_performance/Thresholds/nightly-main.json index a5ce735741c..968f9a35669 100644 --- a/IntegrationTests/tests_04_performance/Thresholds/nightly-main.json +++ b/IntegrationTests/tests_04_performance/Thresholds/nightly-main.json @@ -1,17 +1,16 @@ { - "10000000_asyncsequenceproducer": 19, - "1000000_asyncwriter": 1000050, - "1000_addHandlers": 44050, + "1_reqs_1000_conn": 384050, "1000_addHandlers_sync": 37050, + "1000_addHandlers": 44050, "1000_addRemoveHandlers_handlercontext": 8050, "1000_addRemoveHandlers_handlername": 8050, "1000_addRemoveHandlers_handlertype": 8050, - "1000_autoReadGetAndSet": 18050, "1000_autoReadGetAndSet_sync": 0, + "1000_autoReadGetAndSet": 18050, "1000_copying_bytebufferview_to_array": 1050, "1000_copying_circularbuffer_to_array": 1050, - "1000_getHandlers": 8050, "1000_getHandlers_sync": 35, + "1000_getHandlers": 8050, "1000_reqs_1_conn": 26400, "1000_rst_connections": 145050, "1000_tcpbootstraps": 3050, @@ -19,29 +18,30 @@ "1000_udp_reqs": 6050, "1000_udpbootstraps": 2050, "1000_udpconnections": 75050, - "1_reqs_1000_conn": 384050, + "1000000_asyncwriter": 1000050, + "10000000_asyncsequenceproducer": 20, "assume_isolated_scheduling_10000_executions": 89, "bytebuffer_lots_of_rw": 2050, "creating_10000_headers": 0, "decode_1000_ws_frames": 2050, - "encode_1000_ws_frames_holding_buffer": 3, "encode_1000_ws_frames_holding_buffer_with_mask": 2050, - "encode_1000_ws_frames_holding_buffer_with_space": 3, "encode_1000_ws_frames_holding_buffer_with_space_with_mask": 2050, - "encode_1000_ws_frames_new_buffer": 3050, + "encode_1000_ws_frames_holding_buffer_with_space": 3, + "encode_1000_ws_frames_holding_buffer": 3, "encode_1000_ws_frames_new_buffer_with_mask": 5050, - "encode_1000_ws_frames_new_buffer_with_space": 3050, "encode_1000_ws_frames_new_buffer_with_space_with_mask": 5050, + "encode_1000_ws_frames_new_buffer_with_space": 3050, + "encode_1000_ws_frames_new_buffer": 3050, "execute_hop_10000_tasks": 0, "flat_schedule_10000_tasks": 100100, "flat_schedule_assume_isolated_10000_tasks": 80100, "future_assume_isolated_lots_of_callbacks": 74050, "future_erase_result": 4050, "future_lots_of_callbacks": 74050, - "get_100000_headers_canonical_form": 500050, - "get_100000_headers_canonical_form_trimming_whitespace": 500050, "get_100000_headers_canonical_form_trimming_whitespace_from_long_string": 500050, "get_100000_headers_canonical_form_trimming_whitespace_from_short_string": 500050, + "get_100000_headers_canonical_form_trimming_whitespace": 500050, + "get_100000_headers_canonical_form": 500050, "modifying_1000_circular_buffer_elements": 0, "modifying_byte_buffer_view": 6050, "ping_pong_1000_reqs_1_conn": 314, @@ -54,6 +54,6 @@ "scheduling_10000_executions": 89, "submit_10000_tasks": 20100, "submit_assume_isolated_10000_tasks": 20100, - "udp_1000_reqs_1_conn": 6200, - "udp_1_reqs_1000_conn": 162050 + "udp_1_reqs_1000_conn": 162050, + "udp_1000_reqs_1_conn": 6200 } diff --git a/IntegrationTests/tests_04_performance/Thresholds/nightly-next.json b/IntegrationTests/tests_04_performance/Thresholds/nightly-next.json index 29a7bf1e7c4..31ab97ea2c4 100644 --- a/IntegrationTests/tests_04_performance/Thresholds/nightly-next.json +++ b/IntegrationTests/tests_04_performance/Thresholds/nightly-next.json @@ -1,17 +1,16 @@ { - "10000000_asyncsequenceproducer": 19, - "1000000_asyncwriter": 1000050, - "1000_addHandlers": 44050, + "1_reqs_1000_conn": 384000, "1000_addHandlers_sync": 37050, + "1000_addHandlers": 44050, "1000_addRemoveHandlers_handlercontext": 8050, "1000_addRemoveHandlers_handlername": 8050, "1000_addRemoveHandlers_handlertype": 8050, - "1000_autoReadGetAndSet": 18050, "1000_autoReadGetAndSet_sync": 0, + "1000_autoReadGetAndSet": 18050, "1000_copying_bytebufferview_to_array": 1050, "1000_copying_circularbuffer_to_array": 1050, - "1000_getHandlers": 8050, "1000_getHandlers_sync": 35, + "1000_getHandlers": 8050, "1000_reqs_1_conn": 26400, "1000_rst_connections": 145050, "1000_tcpbootstraps": 3050, @@ -19,29 +18,30 @@ "1000_udp_reqs": 6050, "1000_udpbootstraps": 2050, "1000_udpconnections": 75050, - "1_reqs_1000_conn": 384050, + "1000000_asyncwriter": 1000050, + "10000000_asyncsequenceproducer": 20, "assume_isolated_scheduling_10000_executions": 89, "bytebuffer_lots_of_rw": 2050, "creating_10000_headers": 0, "decode_1000_ws_frames": 2050, - "encode_1000_ws_frames_holding_buffer": 3, "encode_1000_ws_frames_holding_buffer_with_mask": 2050, - "encode_1000_ws_frames_holding_buffer_with_space": 3, "encode_1000_ws_frames_holding_buffer_with_space_with_mask": 2050, - "encode_1000_ws_frames_new_buffer": 3050, + "encode_1000_ws_frames_holding_buffer_with_space": 3, + "encode_1000_ws_frames_holding_buffer": 3, "encode_1000_ws_frames_new_buffer_with_mask": 5050, - "encode_1000_ws_frames_new_buffer_with_space": 3050, "encode_1000_ws_frames_new_buffer_with_space_with_mask": 5050, + "encode_1000_ws_frames_new_buffer_with_space": 3050, + "encode_1000_ws_frames_new_buffer": 3050, "execute_hop_10000_tasks": 0, "flat_schedule_10000_tasks": 100100, - "flat_schedule_assume_isolated_10000_tasks": 90100, + "flat_schedule_assume_isolated_10000_tasks": 80100, "future_assume_isolated_lots_of_callbacks": 74050, "future_erase_result": 4050, "future_lots_of_callbacks": 74050, - "get_100000_headers_canonical_form": 700050, - "get_100000_headers_canonical_form_trimming_whitespace": 700050, - "get_100000_headers_canonical_form_trimming_whitespace_from_long_string": 700050, - "get_100000_headers_canonical_form_trimming_whitespace_from_short_string": 700050, + "get_100000_headers_canonical_form_trimming_whitespace_from_long_string": 500050, + "get_100000_headers_canonical_form_trimming_whitespace_from_short_string": 500050, + "get_100000_headers_canonical_form_trimming_whitespace": 500050, + "get_100000_headers_canonical_form": 500050, "modifying_1000_circular_buffer_elements": 0, "modifying_byte_buffer_view": 6050, "ping_pong_1000_reqs_1_conn": 314, @@ -54,6 +54,6 @@ "scheduling_10000_executions": 89, "submit_10000_tasks": 20100, "submit_assume_isolated_10000_tasks": 20100, - "udp_1000_reqs_1_conn": 6200, - "udp_1_reqs_1000_conn": 162050 -} + "udp_1_reqs_1000_conn": 162050, + "udp_1000_reqs_1_conn": 6200 +} \ No newline at end of file