Netty源码分析第4章(pipeline)---->第3节: handler的删除
Netty源码分析第四章: pipeline
第三节: handler的删除
上一小节我们学习了添加handler的逻辑操作, 这一小节我们学习删除handler的相关逻辑
如果用户在业务逻辑中进行ctx.pipeline().remove(this)这样的写法, 或者ch.pipeline().remove(new SimpleHandler())这样的写法, 则就是对handler进行删除, 我们学习过添加handler的逻辑, 所以对handler删除操作理解起来也会比较容易
我们首先跟到defaultChannelPipeline的remove(handler)的方法中:
public final ChannelPipeline remove(ChannelHandler handler) {
remove(getContextOrDie(handler));
return this;
}
方法体里有个remove()方法, 传入一个 getContextOrDie(handler) 参数, 这个 getContextOrDie(handler) , 其实就是根据handler拿到其包装类HandlerContext对象
我们跟到getContextPrDie这个方法中:
private AbstractChannelHandlerContext getContextOrDie(ChannelHandler handler) {
AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(handler);
//代码省略
}
这里仍然会通过context(handler)方法去寻找, 再跟进去:
public final ChannelHandlerContext context(ChannelHandler handler) {
if (handler == null) {
throw new NullPointerException("handler");
}
//从头遍历节点
AbstractChannelHandlerContext ctx = head.next;
for (;;) {
if (ctx == null) {
return null;
}
//找到handler
if (ctx.handler() == handler) {
return ctx;
}
ctx = ctx.next;
}
}
这里我们看到寻找的方法也非常的简单, 就是从头结点开始遍历, 遍历到如果其包装的handler对象是传入的handler对象, 则返回找到的handlerContext
回到remove(handler)方法:
public final ChannelPipeline remove(ChannelHandler handler) {
remove(getContextOrDie(handler));
return this;
}
继续跟到remove方法中:
private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) { //当前删除的节点不能是head, 也不能是tail
assert ctx != head && ctx != tail; synchronized (this) {
//执行删除操作
remove0(ctx);
if (!registered) {
callHandlerCallbackLater(ctx, false);
return ctx;
} //回调删除handler事件
EventExecutor executor = ctx.executor();
if (!executor.inEventLoop()) {
executor.execute(new Runnable() {
@Override
public void run() {
callHandlerRemoved0(ctx);
}
});
return ctx;
}
}
callHandlerRemoved0(ctx);
return ctx;
}
首先要断言删除的节点不能是tail和head
然后通过remove0(ctx)进行实际的删除操作, 跟到remove0(ctx)中:
private static void remove0(AbstractChannelHandlerContext ctx) {
//当前节点的前置节点
AbstractChannelHandlerContext prev = ctx.prev;
//当前节点的后置节点
AbstractChannelHandlerContext next = ctx.next;
//前置节点的下一个节点设置为后置节点
prev.next = next;
//后置节点的上一个节点设置为前置节点
next.prev = prev;
}
这里的操作也非常简单, 做了一个指针移动的操作, 熟悉双向链表的小伙伴应该不会陌生, 删除节点逻辑大概如下图所示:
4-3-1
回到remove(ctx)方法:
private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) { //当前删除的节点不能是head, 也不能是tail
assert ctx != head && ctx != tail; synchronized (this) {
//执行删除操作
remove0(ctx);
if (!registered) {
callHandlerCallbackLater(ctx, false);
return ctx;
} //回调删除handler事件
EventExecutor executor = ctx.executor();
if (!executor.inEventLoop()) {
executor.execute(new Runnable() {
@Override
public void run() {
callHandlerRemoved0(ctx);
}
});
return ctx;
}
}
callHandlerRemoved0(ctx);
return ctx;
}
我们继续往下看, 如果当前线程不是eventLoop线程则将回调删除事件封装成task放在taskQueue中让eventLoop线程进行执行, 否则, 则直接执行回调删除事件
跟到callHandlerRemoved0(ctx)方法中:
private void callHandlerRemoved0(final AbstractChannelHandlerContext ctx) {
try {
try {
//调用handler的handlerRemoved方法
ctx.handler().handlerRemoved(ctx);
} finally {
//将当前节点状态设置为已移除
ctx.setRemoved();
}
} catch (Throwable t) {
fireExceptionCaught(new ChannelPipelineException(
ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t));
}
}
与添加handler的逻辑一样, 这里会调用当前handler的handlerRemoved方法, 如果用户没有重写该方法, 则会调用其父类的方法, 方法体在ChannelHandlerAdapter类中有定义, 我们跟进去
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { }
同添加handler一样, 也是一个空实现, 这里用户可以通过重写来添加自己需要的逻辑
以上就是删除handler的相关操作
Netty源码分析第4章(pipeline)---->第3节: handler的删除的更多相关文章
- Netty源码分析第4章(pipeline)---->第2节: handler的添加
Netty源码分析第四章: pipeline 第二节: Handler的添加 添加handler, 我们以用户代码为例进行剖析: .childHandler(new ChannelInitialize ...
- Netty源码分析第4章(pipeline)---->第4节: 传播inbound事件
Netty源码分析第四章: pipeline 第四节: 传播inbound事件 有关于inbound事件, 在概述中做过简单的介绍, 就是以自己为基准, 流向自己的事件, 比如最常见的channelR ...
- Netty源码分析第4章(pipeline)---->第5节: 传播outbound事件
Netty源码分析第五章: pipeline 第五节: 传播outBound事件 了解了inbound事件的传播过程, 对于学习outbound事件传输的流程, 也不会太困难 在我们业务代码中, 有可 ...
- Netty源码分析第4章(pipeline)---->第6节: 传播异常事件
Netty源码分析第四章: pipeline 第6节: 传播异常事件 讲完了inbound事件和outbound事件的传输流程, 这一小节剖析异常事件的传输流程 首先我们看一个最最简单的异常处理的场景 ...
- Netty源码分析第4章(pipeline)---->第7节: 前章节内容回顾
Netty源码分析第四章: pipeline 第七节: 前章节内容回顾 我们在第一章和第三章中, 遗留了很多有关事件传输的相关逻辑, 这里带大家一一回顾 首先看两个问题: 1.在客户端接入的时候, N ...
- Netty源码分析第4章(pipeline)---->第1节: pipeline的创建
Netty源码分析第四章: pipeline 概述: pipeline, 顾名思义, 就是管道的意思, 在netty中, 事件在pipeline中传输, 用户可以中断事件, 添加自己的事件处理逻辑, ...
- Netty源码分析第5章(ByteBuf)---->第10节: SocketChannel读取数据过程
Netty源码分析第五章: ByteBuf 第十节: SocketChannel读取数据过程 我们第三章分析过客户端接入的流程, 这一小节带大家剖析客户端发送数据, Server读取数据的流程: 首先 ...
- Netty源码分析第5章(ByteBuf)---->第4节: PooledByteBufAllocator简述
Netty源码分析第五章: ByteBuf 第四节: PooledByteBufAllocator简述 上一小节简单介绍了ByteBufAllocator以及其子类UnPooledByteBufAll ...
- Netty源码分析第5章(ByteBuf)---->第5节: directArena分配缓冲区概述
Netty源码分析第五章: ByteBuf 第五节: directArena分配缓冲区概述 上一小节简单分析了PooledByteBufAllocator中, 线程局部缓存和arean的相关逻辑, 这 ...
随机推荐
- 4-3 R语言函数 mapply
#mapply(函数/函数名,数据,函数相关的函数) > list(rep(1,4),rep(2,3),rep(3,2),rep(4,1)) [[1]] [1] 1 1 1 1 [[2]] [1 ...
- SAP NetWeaver BPM
什么是BPM? BPM是Business Process Management的缩写,翻译过来是业务流程管理.BPM本身并没有明确的定义,它更多的是一种概念,这个概念本身的产生来源于企业对众多业务系统 ...
- docker 部署 redmine 项目管理软件
最近部署一套redmine项目管理程序, ruby部署各种问题,用docker 直接run, 简单方便. . docker run --name=mysql-redmine -d -p : -v /d ...
- pip问题解决方案
错误信息:usr/bin/pip: No such file or directory 解决办法(一共四步,按照下面的步骤来从1到4,最后你会发现问题都解决了): 1.which pip /usr/l ...
- Selenium2+python-unittest之装饰器(@classmethod)
原文地址:http://www.cnblogs.com/yoyoketang/p/6685416.html 前言 前面讲到unittest里面setUp可以在每次执行用例前执行,这样有效的减少了代码量 ...
- Pat乙级1011题:A+B和C
题目:给定区间[-2的31次方, 2的31次方]内的3个整数A.B和C,请判断A+B是否大于C. 我写的代码: del abc(self,a,b,c,i): if a+b>c: print(&q ...
- git 代码分支合并merge提交新修改远程以及本地分支
第一步:创建本地分支 点击右键选择TortoiseGit,选择Create Branch…,在Branch框中填写新分支的名称(若选中”switch to new branch”则直接转到新分支上,省 ...
- Kafka设计解析(十七)Kafka 0.11客户端集群管理工具AdminClient
转载自 huxihx,原文链接 Kafka 0.11客户端集群管理工具AdminClient 很多用户都有直接使用程序API操作Kafka集群的需求.在0.11版本之前,kafka的服务器端代码(即添 ...
- nagios client 端的安装配置 以及 svr端对应的配置(转)
1.下载安装包并解压 $ wget wget http://www.nagios-plugins.org/download/nagios-plugins-2.1.1.tar.gz$ wget http ...
- .NET Core中多语言支持
在.NET Core项目中也是可以使用.resx资源文件,来为程序提供多语言支持.以下我们就以一个.NET Core控制台项目为例,来讲解资源文件的使用. 新建一个.NET Core控制台项目,然后我 ...