Netty之ChannelPipeline(二)移除ChannelHandler

无人久伴 提交于 2020-02-05 02:37:18

上次说了添加,这次看看移除。
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();
            }
        }
    }
    
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!