Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"mallocCountTotal" : 108
"mallocCountTotal": 108
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"mallocCountTotal" : 164376
}
"mallocCountTotal": 82500
}
28 changes: 14 additions & 14 deletions IntegrationTests/tests_04_performance/Thresholds/nightly-main.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
{
"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,
"1000_tcpconnections": 152050,
"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,
Expand All @@ -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
}
36 changes: 18 additions & 18 deletions IntegrationTests/tests_04_performance/Thresholds/nightly-next.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
{
"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,
"1000_tcpconnections": 152050,
"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,
Expand All @@ -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
}
5 changes: 4 additions & 1 deletion Sources/NIOCore/AsyncAwaitSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,10 @@ extension ChannelPipeline {
"ChannelHandlerContext is not Sendable and it is therefore not safe to be used outside of its EventLoop"
)
@inlinable
public func context<Handler: ChannelHandler>(handlerType: Handler.Type) async throws -> ChannelHandlerContext {
@preconcurrency
public func context<Handler: ChannelHandler & _NIOCoreSendableMetatype>(
handlerType: Handler.Type
) async throws -> ChannelHandlerContext {
try await self.context(handlerType: handlerType).map { UnsafeTransfer($0) }.get().wrappedValue
}

Expand Down
15 changes: 12 additions & 3 deletions Sources/NIOCore/ChannelPipeline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,10 @@ 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<Handler: ChannelHandler>(handlerType: Handler.Type) -> EventLoopFuture<ChannelHandlerContext> {
@preconcurrency
public func context<Handler: ChannelHandler & _NIOCoreSendableMetatype>(
handlerType: Handler.Type
) -> EventLoopFuture<ChannelHandlerContext> {
let promise = self.eventLoop.makePromise(of: ChannelHandlerContext.self)

if self.eventLoop.inEventLoop {
Expand All @@ -555,7 +558,10 @@ 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<Handler: ChannelHandler>(type: Handler.Type) -> EventLoopFuture<Void> {
@preconcurrency
public func containsHandler<Handler: ChannelHandler & _NIOCoreSendableMetatype>(
type: Handler.Type
) -> EventLoopFuture<Void> {
self.handler(type: type).map { _ in () }
}

Expand Down Expand Up @@ -2424,7 +2430,10 @@ extension ChannelPipeline: CustomDebugStringConvertible {
/// - Parameters:
/// - type: the type of `ChannelHandler` to return.
@inlinable
public func handler<Handler: ChannelHandler>(type _: Handler.Type) -> EventLoopFuture<Handler> {
@preconcurrency
public func handler<Handler: ChannelHandler & _NIOCoreSendableMetatype>(
type _: Handler.Type
) -> EventLoopFuture<Handler> {
self.context(handlerType: Handler.self).map { context in
guard let typedContext = context.handler as? Handler else {
preconditionFailure(
Expand Down
19 changes: 19 additions & 0 deletions Sources/NIOCore/NIOCoreSendableMetatype.swift
Original file line number Diff line number Diff line change
@@ -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
6 changes: 4 additions & 2 deletions Sources/NIOFileSystem/DirectoryEntries.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<S: AsyncSequence & Sendable>(wrapping sequence: S) where S.Element == Batched.Element {
public init<S: AsyncSequence & Sendable>(wrapping sequence: S)
where S.Element == Batched.Element, S.AsyncIterator: _NIOFileSystemSendableMetatype {
self.batchedSequence = Batched(wrapping: sequence)
}

Expand Down Expand Up @@ -95,7 +96,8 @@ extension DirectoryEntries {
/// Creates a ``DirectoryEntries/Batched`` sequence by wrapping an `AsyncSequence`
/// of directory entry batches.
@preconcurrency
public init<S: AsyncSequence & Sendable>(wrapping sequence: S) where S.Element == Element {
public init<S: AsyncSequence & Sendable>(wrapping sequence: S)
where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype {
self.stream = BufferedOrAnyStream<[DirectoryEntry], DirectoryEntryProducer>(wrapping: sequence)
}

Expand Down
4 changes: 3 additions & 1 deletion Sources/NIOFileSystem/FileChunks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ public struct FileChunks: AsyncSequence, Sendable {
private let stream: BufferedOrAnyStream<ByteBuffer, FileChunkProducer>

/// Create a ``FileChunks`` sequence backed by wrapping an `AsyncSequence`.
public init<S: AsyncSequence & Sendable>(wrapping sequence: S) where S.Element == ByteBuffer {
@preconcurrency
public init<S: AsyncSequence & Sendable>(wrapping sequence: S)
where S.Element == ByteBuffer, S.AsyncIterator: _NIOFileSystemSendableMetatype {
self.stream = BufferedOrAnyStream(wrapping: sequence)
}

Expand Down
8 changes: 5 additions & 3 deletions Sources/NIOFileSystem/Internal/BufferedOrAnyStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ internal enum BufferedOrAnyStream<Element: Sendable, Delegate: NIOAsyncSequenceP
self = .nioThrowingAsyncSequenceProducer(stream)
}

internal init<S: AsyncSequence & Sendable>(wrapping stream: S) where S.Element == Element {
internal init<S: AsyncSequence & Sendable>(wrapping stream: S)
where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype {
self = .anyAsyncSequence(AnyAsyncSequence(wrapping: stream))
}

Expand Down Expand Up @@ -72,7 +73,8 @@ internal enum BufferedOrAnyStream<Element: Sendable, Delegate: NIOAsyncSequenceP
internal struct AnyAsyncSequence<Element>: AsyncSequence, Sendable {
private let _makeAsyncIterator: @Sendable () -> AsyncIterator

internal init<S: AsyncSequence & Sendable>(wrapping sequence: S) where S.Element == Element {
internal init<S: AsyncSequence & Sendable>(wrapping sequence: S)
where S.Element == Element, S.AsyncIterator: _NIOFileSystemSendableMetatype {
self._makeAsyncIterator = {
AsyncIterator(wrapping: sequence.makeAsyncIterator())
}
Expand All @@ -82,7 +84,7 @@ internal struct AnyAsyncSequence<Element>: AsyncSequence, Sendable {
self._makeAsyncIterator()
}

internal struct AsyncIterator: AsyncIteratorProtocol {
internal struct AsyncIterator: AsyncIteratorProtocol, _NIOFileSystemSendableMetatype {
private var iterator: any AsyncIteratorProtocol

init<I: AsyncIteratorProtocol>(wrapping iterator: I) where I.Element == Element {
Expand Down
19 changes: 19 additions & 0 deletions Sources/NIOFileSystem/NIOFileSystemSendableMetatype.swift
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions Sources/NIOPosix/NIOPosixSendableMetatype.swift
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion Sources/NIOPosix/SocketProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
//===----------------------------------------------------------------------===//
import NIOCore

protocol BaseSocketProtocol: CustomStringConvertible {
protocol BaseSocketProtocol: CustomStringConvertible, _NIOPosixSendableMetatype {
associatedtype SelectableType: Selectable

var isOpen: Bool { get }
Expand Down
3 changes: 0 additions & 3 deletions Sources/NIOWebSocket/NIOWebSocketClientUpgrader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,6 @@ public final class NIOTypedWebSocketClientUpgrader<UpgradeResult: Sendable>: 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
Expand Down
4 changes: 2 additions & 2 deletions Tests/NIOHTTP1Tests/HTTPServerUpgradeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extension ChannelPipeline {
try self.assertDoesNotContain(handlerType: HTTPServerUpgradeHandler.self)
}

func assertDoesNotContain<Handler: ChannelHandler>(
func assertDoesNotContain<Handler: ChannelHandler & _NIOCoreSendableMetatype>(
handlerType: Handler.Type,
file: StaticString = #filePath,
line: UInt = #line
Expand All @@ -49,7 +49,7 @@ extension ChannelPipeline {
}
}

func assertContains<Handler: ChannelHandler>(handlerType: Handler.Type) {
func assertContains<Handler: ChannelHandler & _NIOCoreSendableMetatype>(handlerType: Handler.Type) {
XCTAssertNoThrow(try self.containsHandler(type: handlerType).wait(), "did not find handler")
}

Expand Down
Loading