Skip to content

Commit 276b9cb

Browse files
authored
Provide a senable view over the stream multiplexer (#506)
Motivation: The HTTP2StreamMultiplexer isn't `Sendable`, but it has public API for creating streams which must operate from off of the `EventLoop`. Modifications: - Add a `SendableView` over the multiplexer which only provides the methods for creating streams. These are safe to call from any isolation domain. Result: Can create streams from off of the EL.
1 parent 61f6aa4 commit 276b9cb

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ let package = Package(
7171
.product(name: "NIOTLS", package: "swift-nio"),
7272
.product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
7373
.product(name: "Atomics", package: "swift-atomics"),
74-
]
74+
],
75+
swiftSettings: strictConcurrencySettings
7576
),
7677
.target(
7778
name: "NIOHPACK",

Sources/NIOHTTP2/HTTP2StreamMultiplexer.swift

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,18 +339,25 @@ extension HTTP2StreamMultiplexer {
339339
)
340340
sendableView.createStreamChannel(promise: promise, streamStateInitializer)
341341
}
342+
343+
/// Returns a `Sendable` view over the ``HTTP2StreamMultiplexer`` providing only thread-safe
344+
/// APIs.
345+
///
346+
/// This is useful when you need to be able to create streams from off of the event loop.
347+
public var sendableView: SendableView {
348+
SendableView(http2StreamMultiplexer: self, eventLoop: self.channel.eventLoop)
349+
}
342350
}
343351

344352
extension HTTP2StreamMultiplexer {
345-
/// HTTP2StreamMultiplexer.SendableView exposes only the thread-safe API of HTTP2StreamMultiplexer
346-
///
347-
/// We use unckecked Sendable here because we always make sure we are on the right event loop
348-
/// from this code on.
349-
struct SendableView: @unchecked Sendable {
353+
/// ``SendableView`` exposes only the thread-safe API of ``HTTP2StreamMultiplexer``.
354+
public struct SendableView: @unchecked Sendable {
355+
// @unckecked Sendable is fine here: each of the create functions always executes
356+
// onto the appropriate event-loop.
350357
let http2StreamMultiplexer: HTTP2StreamMultiplexer
351358
let eventLoop: EventLoop
352359

353-
func createStreamChannel(
360+
public func createStreamChannel(
354361
promise: EventLoopPromise<Channel>?,
355362
_ streamStateInitializer: @escaping NIOChannelInitializer
356363
) {
@@ -371,7 +378,7 @@ extension HTTP2StreamMultiplexer {
371378
deprecated,
372379
message: "The signature of 'streamStateInitializer' has changed to '(Channel) -> EventLoopFuture<Void>'"
373380
)
374-
func createStreamChannel(
381+
public func createStreamChannel(
375382
promise: EventLoopPromise<Channel>?,
376383
_ streamStateInitializer: @escaping NIOChannelInitializerWithStreamID
377384
) {
@@ -414,3 +421,6 @@ extension HTTP2StreamMultiplexer {
414421
self.commonStreamMultiplexer.requestStreamID(forChannel: channel)
415422
}
416423
}
424+
425+
@available(*, unavailable)
426+
extension HTTP2StreamMultiplexer: Sendable {}

0 commit comments

Comments
 (0)