3-4 注册selector
一 注册selector大纲
1. AbstractChannel.register(channel) //入口
2. this.eventLoop = eventLoop //绑定线程
3. register0() //实际注册
4.register0()调用流程
doRegister() //调用jdk底层的注册方法
fireChannelRegistered() //调用传播事件
二 注册selector流程
1. 进入 AbstractChannel.register(channel)
//channel 注册入口 @Override public final void register(EventLoop eventLoop, final ChannelPromise promise) { ObjectUtil.checkNotNull(eventLoop, "eventLoop"); if (isRegistered()) { promise.setFailure(new IllegalStateException("registered to an event loop already")); return; } if (!isCompatible(eventLoop)) { promise.setFailure( new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName())); return; } //设置eventLoop AbstractChannel.this.eventLoop = eventLoop; if (eventLoop.inEventLoop()) { //channel 实际注册方法 register0(promise); } else { try { eventLoop.execute(new Runnable() { @Override public void run() { register0(promise); } }); } catch (Throwable t) { logger.warn( "Force-closing a channel whose registration task was not accepted by an event loop: {}", AbstractChannel.this, t); closeForcibly(); closeFuture.setClosed(); safeSetFailure(promise, t); } } }
AbstractChannel.register(channel) 方法很简单,先保存eventLoop,然后调用 AbstractUnsafe#register0 方法继续注册 ChannelFuture
进入 AbstractUnsafe#register0 方法
//注册 channel private void register0(ChannelPromise promise) { try { // check if the channel is still open as it could be closed in the mean time when the register // call was outside of the eventLoop if (!promise.setUncancellable() || !ensureOpen(promise)) { return; } boolean firstRegistration = neverRegistered; /** * 调用 {@link AbstractNioChannel#doRegister()} 注册 */ doRegister(); neverRegistered = false; registered = true; // Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the // user may already fire events through the pipeline in the ChannelFutureListener. //调用 ChannelHandler 的 handlerAdded 方法 pipeline.invokeHandlerAddedIfNeeded(); safeSetSuccess(promise); // 触发 channelRegistered 事件 pipeline.fireChannelRegistered(); // Only fire a channelActive if the channel has never been registered. This prevents firing // multiple channel actives if the channel is deregistered and re-registered. if (isActive()) { if (firstRegistration) { // 触发 channelActive 事件 pipeline.fireChannelActive(); } else if (config().isAutoRead()) { // This channel was registered before and autoRead() is set. This means we need to begin read // again so that we process inbound data. // // See https://github.com/netty/netty/issues/4805 beginRead(); } } } catch (Throwable t) { // Close the channel directly to avoid FD leak. closeForcibly(); closeFuture.setClosed(); safeSetFailure(promise, t); } }
AbstractUnsafe#register0 方法继续调用 AbstractNioChannel#doRegister() 方法注册,接着按顺序触发 handlerAdded、channelRegistered、channelActive 事件
进入 AbstractNioChannel#doRegister() 方法
@Override protected void doRegister() throws Exception { boolean selected = false; for (;;) { try { //调用 nio 的channel 注册 Selector,这里可以看出 register 保存的 attachment 为当前 AbstractNioChannel selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this); return; } catch (CancelledKeyException e) { if (!selected) { // Force the Selector to select now as the "canceled" SelectionKey may still be // cached and not removed because no Select.select(..) operation was called yet. eventLoop().selectNow(); selected = true; } else { // We forced a select operation on the selector before but the SelectionKey is still cached // for whatever reason. JDK bug ? throw e; } } } }
AbstractNioChannel#doRegister() 方法就调用 jdk 底层的 nio 的 channel 注册了 selector,并且从这里可以看出 register 保存的 attachment 为当前 AbstractNioChannel,这在后续的 processSelectionKey 中会用到
至此注册selector 结束,注册selector 很简单,主要就以下几步
- 保存 eventLoop
- 调用 jdk 底层的 nio 的 channel 注册了 selector
- 依次触发 handlerAdded、channelRegistered、channelActive 事件

浙公网安备 33010602011771号