gen_event中的handler和supervised handler
呃,在gen_event中有两个添加handler的方法
gen_event:add_handler/3 gen_event:add_sup_handler/3
一开始总是有些迷惑两者的区别,今天查看了gen_event源码,总算弄清两者的区别。
add_handler添加的只是把gen_event作为容器,仅仅在适当的时间调用模块的回调函数。(后面我描述为normal handler)
而add_sup_hander除了在适当的时间调用模块的回调函数以外,同时link到调用该函数的进程。(后面我描述为supervised handler)
首先看看在gen_event中描述handler的record
-record(handler, {module :: atom(),id = false,state,supervised = false :: 'false' | pid()}).
supervised字段用来区分是那种类型的handler,
首先我们查看一下,添加两种类型的handler实际做了什么事。
%% server_add_handler(Handler, Args, MSL) -> {Ret, MSL'}. %% where MSL = [#handler{}] %% Ret goes to the top level MSL' is the new internal state of the %% event handlerserver_add_handler({Mod,Id}, Args, MSL) ->Handler = #handler{module = Mod,id = Id},server_add_handler(Mod, Handler, Args, MSL); server_add_handler(Mod, Args, MSL) -> Handler = #handler{module = Mod},server_add_handler(Mod, Handler, Args, MSL).server_add_handler(Mod, Handler, Args, MSL) ->case catch Mod:init(Args) of{ok, State} ->{false, ok, [Handler#handler{state = State}|MSL]};{ok, State, hibernate} ->{true, ok, [Handler#handler{state = State}|MSL]};Other ->{false, Other, MSL}end.%% Set up a link to the supervising process. %% (Ought to be unidirected links here, Erl5.0 !!) %% NOTE: This link will not be removed then the %% handler is removed in case another handler has %% own link to this process. server_add_sup_handler({Mod,Id}, Args, MSL, Parent) ->link(Parent),Handler = #handler{module = Mod,id = Id,supervised = Parent},server_add_handler(Mod, Handler, Args, MSL); server_add_sup_handler(Mod, Args, MSL, Parent) -> link(Parent),Handler = #handler{module = Mod,supervised = Parent},server_add_handler(Mod, Handler, Args, MSL).
从上面的代码可以看到,如果添加的是normal handler,supervised保持为默认的'false',
如果为supervised handler,则存放调用改函数时候的进程id。
最后,都调用了Mod:init/1函数,将生成handler添加进handlers 列表中。
接下来,我们再看看当gen_event接受到'EXIT'消息时候,做的处理。
%% First terminate the supervised (if exists) handlers and %% then inform other handlers. %% We do not know if any handler really is interested but it %% may be so ! handle_exit(From, Reason, MSL, SName) ->MSL1 = terminate_supervised(From, Reason, MSL, SName),{_,MSL2}=server_notify({'EXIT', From, Reason}, handle_info, MSL1, SName),MSL2.terminate_supervised(Pid, Reason, MSL, SName) ->F = fun(Ha) when Ha#handler.supervised =:= Pid ->do_terminate(Ha#handler.module,Ha,{stop,Reason},Ha#handler.state,{parent_terminated, {Pid,Reason}},SName,shutdown),false;(_) ->trueend,lists:filter(F, MSL).do_terminate(Mod, Handler, Args, State, LastIn, SName, Reason) ->Res = (catch Mod:terminate(Args, State)),report_terminate(Handler, Reason, Args, State, LastIn, SName, Res),Res.
因为在添加supervised handler时候,我们link到了调用者进程。
所以当收到'EXIT'通知消息的时候,我们必须判断是否为supervised 进程的终止消息,如果是的话,需要删除handler列表中的该supervised handler。
同时调用Mod:terminate/2函数,并通知其他的handlers。
当停止gen_event时候:
terminate_server(Reason, Parent, MSL, ServerName) ->stop_handlers(MSL, ServerName),do_unlink(Parent, MSL),exit(Reason).%% unlink the supervisor process of all supervised handlers. %% We do not want a handler supervisor to EXIT due to the %% termination of the event manager (server). %% Do not unlink Parent ! do_unlink(Parent, MSL) ->lists:foreach(fun(Handler) when Handler#handler.supervised =:= Parent ->true;(Handler) when is_pid(Handler#handler.supervised) ->unlink(Handler#handler.supervised),true;(_) ->trueend,MSL).
我们也需要判断supervised handler,对进程进行unlink,当gen_event进程结束时候,并不会强制supervisored handler进程结束。
而在下面两个函数调用时候:
gen_event:delete_handler/3 gen_event:swap_sup_handler/3
除了正常的逻辑,同时向supervisored handler的宿主进程发送{gen_event_EXIT,Handler,Reason},supervised handler进程可以依此消息来做出处理。。。
转载于:https://www.cnblogs.com/star-star/archive/2013/05/23/3095203.html
gen_event中的handler和supervised handler相关推荐
- 【Android 异步操作】Handler ( 主线程中的 Handler 与 Looper | Handler 原理简介 )
文章目录 一.主线程中的 Handler 与 Looper 二.Handler 原理简介 一.主线程中的 Handler 与 Looper Android 系统中 , 点击图标启动一个应用进程 , 就 ...
- Android中的消息机制:Handler消息传递机制
参考<疯狂android讲义>第2版3.5 P214 一.背景 出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题.为 ...
- 【Android 异步操作】手写 Handler ( Handler 发送与处理消息 | Handler 初始化 | 完整 Handler 代码 )
文章目录 一.Handler 发送与处理消息 ( 两大功能 ) 二.Handler 初始化 三.完整 Handler 代码 一.Handler 发送与处理消息 ( 两大功能 ) Handler 有两个 ...
- android handler内存,Android handler之内存泄露原因揭示
关于handler机制大家可以看前面专题Android面试精选--再聊android Handler机制.今天我们要说的重点是 handler为什么会发生内存泄露? 我们先从源头说起,应用刚启动时,第 ...
- 85、android handler的警告Handler Class Should be Static or Leaks Occur
转载:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1106/1922.html 在使用Handler更新UI的时候,我是这样写 ...
- 安卓handler的用法,handler举例
原帖跳转: link 一.Handler的定义: Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用.比如可以用handler发送一个message,然后在 ...
- handler.post和handler.sendMessage的区别和联系
现在大部分人都很熟悉handler这个东西了,我们常用handler的场景无非有两个: 1. 异步更新UI 2. 延时任务 但是我一直有一个困惑,就是handler.post(r)这个方法有什么独特的 ...
- Handler完全解读——Handler的使用
个人博客:https://blog.N0tExpectErr0r.cn 小专栏:https://xiaozhuanlan.com/N0tExpectErr0r Handler完全解读--Handler ...
- 继承Handler还是实现Handler.Callback?
Android的Handler提供了多种创建方式: package com.chanryma.demo;import android.os.Handler; import android.os.Mes ...
最新文章
- 中国队拿下口罩人脸识别世界第一!还将推出全球最大公开人脸数据集
- debugger markup language帮助文档(DML)
- Eclipse中的checkstyle插件
- 计算机网络【二】物理层基础知识
- C 怎么读取Cpp文件_python之调用C加速计算(一)
- 挖一挖产品经理的核心竞争力
- linux打开文件异常
- 9.卷1(套接字联网API)---基本SCTP套接字编程
- 【Scratch案例教学】scratch旋转风车 ​​​​scratch编程案例教学 scratch创意编程 少儿编程教案
- 【错误信息】Maximum call stack size exceeded
- 软件测试面试题目—接口测试面试题,梦寐以求的答案来了
- 非极大值抑制(Non-Maximum Suppression,NMS)
- mtk平台sensor分析一:alsps框架下的光距感驱动流程
- 情人节快乐(转)十五首最美爱情古诗词,伴你过一个温馨浪漫的情人节
- 运输小猫(斜率优化)
- FSA-Net学习笔记
- 多租户:防止意外创建可插拔数据库(PDB)- Lone-PDB
- 关于面向对象(OOB)的一些理解。主要是封装、继承、多态。
- C++仿照标准字符串类string,设计一个自己的字符串类String
- Markdown语法笔记