Is ChannelHandler's property thread safe?

Hi there. I'm new to SwiftNIO, so I would ask some newbie questions

I have been looking at swift-nio-extras/RequestResponseHandler.swift at main · apple/swift-nio-extras · GitHub, which has a property State

I notice that the state is checked and changed in errCaught and only checked ChannelRead and write()

I wanted to ask that, is this behaviour supposed to be thread safe?

e.g. The promiseBuffer is only purged in errCaught, and in normal cases, channelRead and errCaught could have a race condition for state.

If I recall correctly, the Channel{X}Handler protocol methods are guaranteed to be invoked by SwiftNIO on the same EventLoop that the ChannelPipeline the handler is registered with, provided you follow the assumptions that SwiftNIO is built on.

Primarily being, you are not using a shared handler across multiple Channels

Hi there.

It's not on multiple Channels, but the exact same channel. I was asking that, if in this one channel, the first channelRead has errors, and lead to errCaught function call, and the second channelRead kicks in at the same time with errCaught, it looks like they will race condition on the state.

The example simply check state without any lock, so I'm asking the question.

the Channel{X}Handler protocol methods are guaranteed to be invoked by SwiftNIO on the same EventLoop that the ChannelPipeline the handler is registered with

If this is true, then multiple channelRead and errCaught should be serialized? Can any one help to confirm?

Yes.

Yes.

To be entirely clear: if a ChannelHandler instance is added to only one Channel, then all ChannelHandler methods will be dispatched on the event loop thread that owns the Channel. There is thus no requirement to synchronise access to that state. This is also mentioned in our README:

One of the important notes about ChannelPipeline s is that they are thread-safe. This is very important for writing SwiftNIO applications, as it allows you to write much simpler ChannelHandler s in the knowledge that they will not require synchronization.

There is one way to violate this guarantee, and that is to use the same ChannelHandler instance in multiple channels. These multiple channels may exist on separate event loops and therefore the synchronisation guarantee is broken. This is rarely useful, so unless you absolutely know you need it you should simply never do this. The easiest way to guarantee that you never do that is to create all ChannelHandler objects in your channelInitializer.

1 Like