Netty之ChannelPipeline(二)移除ChannelHandler

上次说了添加,这次看看移除。
remove(ChannelHandler handler)方法,从pipeline移除指定ChannelHandler对象

@Override
public final ChannelPipeline remove(ChannelHandler handler) {
     
    remove(getContextOrDie(handler));
    return this;
}

getContextOrDie(ChannelHandler handler)方法获得相应AbstractChannelHandlerContext节点:

private AbstractChannelHandlerContext getContextOrDie(ChannelHandler handler) {
     
    AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(handler);
    if (ctx == null) {
      
    //若得不到节点,抛异常
        throw new NoSuchElementException(handler.getClass().getName());
    } else {
     
        return ctx;
    }
}

@Override
public final ChannelHandlerContext context(ChannelHandler handler) {
     
    if (handler == null) {
     
        throw new NullPointerException("handler");
    }
    AbstractChannelHandlerContext ctx = head.next;
    // 循环,获得指定 ChannelHandler 对象的节点
    for (;;) {
     
        if (ctx == null) {
     
            return null;
        }
        if (ctx.handler() == handler) {
      
        // ChannelHandler 相等
            return ctx;
        }
        ctx = ctx.next;
    }
}

remove(AbstractChannelHandlerContext ctx) 方法,移除指定 AbstractChannelHandlerContext 节点:

 private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) {
     
     assert ctx != head && ctx != tail;
 
     synchronized (this) {
      
     	 //防止多线程并发操作 pipeline 底层的双向链表
         // 移除节点
         remove0(ctx);
         // If the registered is false it means that the channel was not registered on an eventloop yet.
         // In this case we remove the context from the pipeline and add a task that will call
         // ChannelHandler.handlerRemoved(...) once the channel is registered.
         if (!registered) {
     
         //Channel未注册
         //添加PendingHandlerRemovedTask回调,在Channel注册完成后执行该回调。
             callHandlerCallbackLater(ctx, false);
             return ctx;
         }
         EventExecutor executor = ctx.executor();
         // 不在 EventLoop 的线程中。
         if (!executor.inEventLoop()) {
     
             // 提交 EventLoop 中,
             executor.execute(new Runnable() {
     
                 @Override
                 public void run() {
     
                 //执行回调 ChannelHandler removed 事件
                     callHandlerRemoved0(ctx);
                 }
             });
             return ctx;
         }
     }
 
     // 回调 ChannelHandler removed 事件
     callHandlerRemoved0(ctx);
     return ctx;
 }

remove0(AbstractChannelHandlerContext ctx) 方法,从 pipeline 移除指定的 AbstractChannelHandlerContext 节点。

private static void remove0(AbstractChannelHandlerContext ctx) {
     
    // 获得移除节点的前后节点
    AbstractChannelHandlerContext prev = ctx.prev;
    AbstractChannelHandlerContext next = ctx.next;
    // 前后节点互相指向
    prev.next = next;
    next.prev = prev;
}

callHandlerRemoved0(AbstractChannelHandlerContext) 方法,执行回调 ChannelHandler 移除完成( removed )事件:

 private void callHandlerRemoved0(final AbstractChannelHandlerContext ctx) {
     
     // Notify the complete removal.
     try {
     
         try {
     
             // 回调 ChannelHandler 移除完成( removed )事件,释放ChannelHandler占用的资源(由于这个方法的执行在EventLoop线程内,所以要尽量避免执行时间过长)
             ctx.handler().handlerRemoved(ctx);
         } finally {
     
             // 设置 AbstractChannelHandlerContext 已移除
             ctx.setRemoved();
         }
     } catch (Throwable t) {
     
         fireExceptionCaught(new ChannelPipelineException(
                 ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t));
     }
 }

PendingHandlerRemovedTask 实现 PendingHandlerCallback 抽象类,用于回调移除 ChannelHandler 节点:

private final class PendingHandlerRemovedTask extends PendingHandlerCallback {
     

    PendingHandlerRemovedTask(AbstractChannelHandlerContext ctx) {
     
        super(ctx);
    }

    @Override
    public void run() {
     
        callHandlerRemoved0(ctx);
    }

    @Override
    void execute() {
     
        EventExecutor executor = ctx.executor();
        // 在 EventLoop 的线程中,回调 ChannelHandler removed 事件
        if (executor.inEventLoop()) {
     
            callHandlerRemoved0(ctx);
        } else {
     
            // 提交 EventLoop 中,执行回调 ChannelHandler removed 事件
            try {
     
                executor.execute(this); 
            } catch (RejectedExecutionException e) {
     
                if (logger.isWarnEnabled()) {
     
                    logger.warn(
                            "Can't invoke handlerRemoved() as the EventExecutor {} rejected it," +
                                    " removing handler {}.", executor, ctx.name(), e);
                }
                // 标记 AbstractChannelHandlerContext 为已移除
                // remove0(...) was call before so just call AbstractChannelHandlerContext.setRemoved().
                ctx.setRemoved();
            }
        }
    }
    
}

你可能感兴趣的:(Netty)