@Sendable and pipeline configuration

is it now necessary to construct channel handlers inside the EventLoopFuture continuation?

return  channel.pipeline.addHandler(tlsHandler).flatMap 
{
        channel.pipeline.configureHTTPServerPipeline(withErrorHandling: true)
        .flatMap 
    {
        // this closure is @Sendable now since v2.41
        channel.pipeline.addHandler(...)
    }
}

With the current concurrency checking semantics this is the only safe way the compiler understands. EventLoopFutures are not guaranteed to be completed on the current thread and therefore all functions you pass to them need to be @Sendable. However, this is not ideal and we are aware of this problem. In NIO we often guarantee that a returned EventLoopFuture will be completed on a particular EventLoop. We have a CurrentEventLoop proposal which should improve the situation. It will in your use case allow you to use a non-Sendable ChannelHandler initialised in the function you pass to channelInitializer or childChannelInitializer (with a little bit of extra code).

3 Likes

To expand on this a bit: Sendable in Swift is broadly equivalent to both Send and Sync from Rust. If you construct the handler from outside the event loop thread, we need you to support Send-ing it into the Event Loop thread. Unfortunately, Swift can't spell this idea. As a result, we have had to adopt the more conservative path. @dnadoba's proposal will substantially help matters, but to fully resolve it Swift will need to grow a few more lifetime features.

4 Likes