2016-11-08 6 views
0

Весь следующий код от Netty4.0.31.Final. Канал ServerBootstrap - NioServerSocketChannel.Возможно ли, что execute.fireChannelActive() выполняется дважды при выполнении ServerBootstrap.bind()?

Основная логика ServerBootstrap.bind(int) в AbstractBootstrap.doBind(SocketAddress):

private ChannelFuture doBind(final SocketAddress localAddress) { 
     final ChannelFuture regFuture = initAndRegister(); 
     ... 
     if (regFuture.isDone()) { 
      ... 
      doBind0(regFuture, channel, localAddress, promise); 
      ... 
     } else { 
      regFuture.addListener(new ChannelFutureListener() { 
       @Override 
       public void operationComplete(ChannelFuture future) throws Exception { 
        ... 
        doBind0(regFuture, channel, localAddress, promise); 
       } 
      }); 
     } 
} 

Код в initAndRegister() наконец переходит в AbstractUnsafe.register0(ChannelPromise promise):

private void register0(ChannelPromise promise) { 
     try { 
      ... 
      boolean firstRegistration = neverRegistered; 
      doRegister(); 
      ... 
      if (firstRegistration && isActive()) { 
       pipeline.fireChannelActive(); 
      } 
     } catch (Throwable t) { 
      ... 
     } 
} 

Как вы можете видеть, pipeline.fireChannelActive() могут быть выполнены здесь.

Давайте обратно AbstractBootstrap.doBind(SocketAddress), в doBind0(regFuture, channel, localAddress, promise) код, наконец, переходит в AbstractUnsafe.bind(SocketAddress,ChannelPromise):

public final void bind(final SocketAddress localAddress, final ChannelPromise promise) { 
     ... 
     boolean wasActive = isActive(); 
     try { 
      doBind(localAddress); 
     } catch (Throwable t) { 
      ... 
     } 

     if (!wasActive && isActive()) { 
      invokeLater(new OneTimeTask() { 
       @Override 
       public void run() { 
        pipeline.fireChannelActive(); 
       } 
      }); 
     } 
     ... 
    } 

Как вы можете видеть, pipeline.fireChannelActive() также могут быть выполнены здесь.

Итак, есть ли возможность, что pipeline.fireChannelActive() выполняется дважды при создании и привязке одного NioServerSocketChannel?

ответ

1

Только если isActive может перевернуть флоп от истины до значения false, чтобы true снова в указанном потоке. Я думаю, что он может идти только активным один раз, так что ложь -> правда -> ложь

Соответствующий код из вашего поста:

boolean firstRegistration = neverRegistered; 
... 
if (firstRegistration && isActive()) { 
    pipeline.fireChannelActive(); // isActive must be TRUE 
} 
... 
boolean wasActive = isActive(); 
... 
// If fireChannelActive was fired, then wasActive would be true, 
// preventing it from firing again 
if (!wasActive && isActive()) { 
    invokeLater(new OneTimeTask() { 
     @Override 
     public void run() { 
      pipeline.fireChannelActive(); 
+0

Да, я не знаю ответа нет в настоящее время. Но ключевой момент (или другое объяснение) заключается в том, что 'AbstractUnsafe.register0 (ChannelPromise promise)' и 'AbstractUnsafe.bind (SocketAddress, ChannelPromise)' оба исполняются EventLoop. 'AbstractUnsafe.register0 (обещание ChannelPromise)' выполняется до 'AbstractUnsafe.bind (SocketAddress, ChannelPromise)', поэтому 'isActive()' вернет false в 'AbstractUnsafe.register0 (обещание ChannelPromise)'. – labmem