2016-11-08 6 views
0

次のコードはすべてNetty4.0.31.Finalのものです。 ServerBootstrapさんのチャンネルはNioServerSocketChannelです。ServerBootstrap.bind()の実行時にpipeline.fireChannelActive()が2回実行される可能性はありますか?

ServerBootstrap.bind(int)のメインロジックはAbstractBootstrap.doBind(SocketAddress)である:initAndRegister()

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); 
       } 
      }); 
     } 
} 

コードが最終的に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()もここで実行することができます。

NioServerSocketChannelを作成してバインドすると、pipeline.fireChannelActive()が2回実行される可能性はありますか?

答えて

1

あなたが指摘したフローで、isActiveが真から偽へのフリップフロップを再び真に戻すことができない限り、そうではありません。私はそれだけで、一度そう偽アクティブ行くことができると思います - >真 - あなたのポストから>偽

関連するコード:

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 promise)'は 'AbstractUnsafe.bind(SocketAddress、ChannelPromise)'の前に実行されるため、 'isActive()'は 'AbstractUnsafe.register0(ChannelPromise promise)'でfalseを返します。 – labmem

関連する問題