Channel concurrency question

I haven't used NIO in a bit and am struggling to remember: what is the concurrency policy for interacting with Channel? Are calls to writeAndFlush and friends synchronized internally, or do I need to ensure I am on the vent loop by calling channel.eventLoop.execute { } and only call those function in the body of the closure? I don't see anywhere where this is documented.

Doesn't seem to be documented, but IIRC channel writes are thread safe, handler operations are not.

Yes, all Channel operations are thread safe. Documented on the Channel docs.

(Conversely, all ChannelHandlerContext operations must be done on the Channel's eventLoop. That seems to unfortunately be missing in the ChannelHandlerContext docs. It'd be awesome if somebody would like to add a PR adding this.)

Generally: The Channel itself is completely thread-safe and you can do whatever you want with it. The event-processing inside a Channel always happens on Channel.eventLoop. That means you'll only be called on the right EventLoop and you're expected to not call anything outside of the correct EventLoop. In return you get performance and you get to manage ChannelHandlerContext state without locks.

Thanks for the links! I guess my brain is sometimes blind to things in big blocks at the top ;)

One small follow up: is it safe to “escape” a ChannelHandlerContext? For example, saving it in a property of the handler in handlerAdded (and setting it to nil in handlerRemoved) or should they only be used in the body of the handler functions?

That's fine yeah. But you are then responsible for making sure no calls are happening off context.eventLoop === context.channel.evenLoop. In debug mode, NIO will police this and crash in assertInEventLoop.

Said that, I would recommend to not escape it too far (deliberately trying to stay vague here) just to keep the complexity as low as possible. I'd recommend to keep the ChannelPipeline (which is the list of ChannelHandlers represented by a ChannelHandlerContext each) a pipeline. So the information should either flow inbound ('from the network') or outbound ('to the network') and not like spaghettis in a pot :slight_smile:.

2 Likes