3-4 注册selector

一  注册selector大纲

 1.  AbstractChannel.register(channel)  //入口

 2.  this.eventLoop = eventLoop  //绑定线程

 3.  register0()  //实际注册

 4.register0()调用流程

  doRegister()  //调用jdk底层的注册方法

  fireChannelRegistered()  //调用传播事件

二  注册selector流程

  @Override
    public final void register(EventLoop eventLoop, final ChannelPromise promise) {
        if (eventLoop == null) {
            throw new NullPointerException("eventLoop");
        }
        if (promise == null) {
            throw new NullPointerException("promise");
        }
        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;
        }

        // 1. 添加eventLoop
        if (AbstractChannel.this.eventLoop == null) {
            AbstractChannel.this.eventLoop = new PausableChannelEventLoop(eventLoop);
        } else {
            AbstractChannel.this.eventLoop.unwrapped = eventLoop;
        }

        if (eventLoop.inEventLoop()) {
            //2. 调用实际的注册方法
            register0(promise);
        } else {
            try {
                eventLoop.execute(new OneTimeTask() {
                    @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);
            }
        }
    }
    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;

            //1.调用jdk底层的注册方法
            doRegister();
            neverRegistered = false;
            registered = true;
            eventLoop.acceptNewTasks();
            safeSetSuccess(promise);
            //2. 传播事件
            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 (firstRegistration && isActive()) {
                pipeline.fireChannelActive();
            }
        } catch (Throwable t) {
            // Close the channel directly to avoid FD leak.
            closeForcibly();
            closeFuture.setClosed();
            safeSetFailure(promise, t);
        }
    }
    @Override
    protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
                //调用jdk底层的register方法注册
                selectionKey = javaChannel().register(((NioEventLoop) eventLoop().unwrap()).selector, 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.
                    ((NioEventLoop) eventLoop().unwrap()).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;
                }
            }
        }
    }

猜你喜欢

转载自www.cnblogs.com/programmlover/p/11924879.html
3-4