erlang四大behaviour之三-gen_event

来源:http://www.cnblogs.com/puputu/articles/1689623.html

1. 事件处理规则

在OTP中,事件管理器是一个事件可以发送到的命名对象,一个事件可以是一个错误、一个警告、或者一些要写入日志的信息

在事件管理器中,有0个、一个或者多个事件处理器被安装,当事件管理器被一个事件通知时,这个事件将被安装在事件管理器中的事件处理器处理,

事件管理器用一个进程实现,事件处理器用回调模块实现。事件管理器本质上维护一个{Module, State}列表,每一个Module为一个事件处理器,而State为事件处理器的内部状态。

2. 例子

事件处理器的回调模块把错误信息写入终端

-module(terminal_logger).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
    {ok, []}.
handle_event(ErrorMsg, State) ->
    io:format("***Error*** ~p~n", [ErrorMsg]),
    {ok, State}.
terminate(_Args, _State) ->
    ok.

事件处理器的回调模块把错误信息写入文件

-module(file_logger).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(File) ->
    {ok, Fd} = file:open(File, read),
    {ok, Fd}.
handle_event(ErrorMsg, Fd) ->
    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    {ok, Fd}.
terminate(_Args, Fd) ->
    file:close(Fd).

3. 启动事件管理器

调用gen_event:start_link({local, error_man})

启动管理器,这个函数生成并连接到一个新进程,参数{local, error_man}指定名称,在这个例子中,事件管理器被局部注册为error_man

假如忽略名称,那么事件管理器不会被注册,它的PID将被使用。名称也可以是这种形式{global, Name},这样,事件管理器的名称是用global:register_name/2注册的。

假如事件管理器是监控树的一部分,那么gen_event:start_link必须被使用,也就是被监控树启动,而gen_event:start启动单独的事件管理器,也就是事件管理器不是监控树的一部分。

4. 添加事件处理器

下面的例子显示怎样启动一个事件管理器和添加一个事件处理器

1> gen_event:start({local, error_man}).
{ok,<0.31.0>}
2> gen_event:add_handler(error_man, terminal_logger, []).
ok

gen_event:add_handler(error_man, terminal_logger, [])为error_man添加处理器terminal_logger,事件管理器调用terminal_logger:init([])这个回调函数, []是参数,init要返回一个{ok, State},State是事件处理器的内部状态

init(_Args) ->
    {ok, []}.

这里,init不需要任何输入参数,对于terminal_logger,也没使用内部状态,对于file_logger,内部状态保存了打开的文件描述符

init(File) ->
    {ok, Fd} = file:open(File, read),
    {ok, Fd}.

5. 关于事件通知

3> gen_event:notify(error_man, no_reply).
***Error*** no_reply
ok

error_man是事件管理器的名称,no_reply是事件,事件作为消息发送给事件管理器,当事件被收到时,事件管理器为每个安装的事件处理器按安 装次序调用handle_event(Event, State),这个函数期待返回{ok, State1},State1是事件处理器的新状态。

在terminal_logger中

handle_event(ErrorMsg, State) ->
    io:format("***Error*** ~p~n", [ErrorMsg]),
    {ok, State}.

在file_logger中

handle_event(ErrorMsg, Fd) ->
    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    {ok, Fd}.

6. 删除一个事件处理器

gen_event:delete_handler(error_man, terminal_logger, []),这个函数向事件管理器error_man发送了一个消息,告诉他删除terminal_logger这个事件处理器,事件管理器将调用 terminal_logger:terminate([], State),参数[]是delete_handler的第三个参数,terminate以init相反的方向调用,以完成清理工作,返回值被忽略。

在terminal_logger中,没有清理动作

terminate(_Args, _State) ->
    ok.

在file_logger中,文件描述符被关掉

terminate(_Args, Fd) ->
    file:close(Fd).

7. 停止

当事件管理器被停止,它给每个注册的事件处理器调用terminate/2的机会,就好像事件处理器被删除一样。如果事件管理器是监控树的一部分,不需要显示的停止事件管理器。当事件管理器作为单独进程使用时,则调用gen_event:stop(error_man).

时间: 2024-08-03 14:32:51

erlang四大behaviour之三-gen_event的相关文章

erlang四大behaviour之四-supervisor

http://www.cnblogs.com/puputu/articles/1689621.html 1. 监督规则 一个监督者负责启动.停止.监控他的子进程.监督者的一个基本概念就是当必要的时候重启子进程保证它们的存活 哪个子进程要重启和被监控是由一个子规程列表决定的,子进程按照列表中指定的顺序启动,并按相反的顺序终止 2. 实例 监督者的回调模块 -module(ch_sup).  -behaviour(supervisor).  -export([start_link/0]).  -ex

erlang四大behaviour之二-gen_fsm

来源:http://www.cnblogs.com/puputu/articles/1701012.html 今天介绍erlang的一个非常重要的behaviour,就是gen_fsm-有限状态机,有限状态机的作用非常之多,比如文本解析,模式匹配.游戏逻辑等等方面的处理都是它的强项,所以这个behaviour非常之重要 1. 有限状态机 有限状态机可以用下面这个公式来表达 State(S) x Event(E) -> Actions(A), State(S') 表示的就是在S状态时如果有事件E发

Android 四大组件之三(广播)

1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通信方式,可以使用的场景如下: 1.同一app内部的同一组件内的消息通信(单个或多个线程之间): 2.同一app内部的不同组件之间的消息通信(单个进程): 3.同一app具有多个进程的不同组件之间的消息通信: 4.不同app之间的组件之间消息通信: 5.Android系统在特定情况下与App之间的消息

VFS四大对象之三 struct dentry

继上一篇文章介绍了inode结构体:继续介绍目录项dentry: 三.dentry结构体 目录项:目录项是描述文件的逻辑属性,只存在于内存中,并没有实际对应的磁盘上的描述,更确切的说是存在于内存的目录项缓存,为了提高查找性能而设计.注意不管是文件夹还是最终的文件,都是属于目录项,所有的目录项在一起构成一颗庞大的目录树.例如:open一个文件/home/xxx/yyy.txt,那么/.home.xxx.yyy.txt都是一个目录项,VFS在查找的时候,根据一层一层的目录项找到对应的每个目录项的in

8、四大组件之三-ContentProvider

课程目标: 理解ContentProvider的作用及好处 认清ContentProvider与数据存储的关系 掌握ContentProvider对外提供的数据模型形式 能够编写ContentResolver的增删改查 能够自定义一个ContentProvider ,能够提供进程间访问 了解ContentProvider 内部机制 重点难点: ContentProvider与数据操作的关系 ContentProvider内部机制 考核目标: 说说ContentProvider与Android数据

《逐梦旅程 WINDOWS游戏编程之从零开始》笔记7——四大变换

第13章 世界变换,取景变换,投影变换,视口变换 在Direct3D中,如果为进行任何空间坐标变换而直接绘图的话,图形将始终处于应用程序窗口的中心位置,默认这个位置就成为世界坐标系的原点(0,0,0).而且我们也不能改变观察图形的视角方向.默认情况下的观察方向是世界坐标系的z轴正向方向. 世界变换运算是为了能在世界空间中的指定位置来绘制图形 取景变换运算是为了以不同的视角观察图形 投影变换为了将相对较远的图形投影到同一个平面上并体现出"近大远小"的真实视觉效果 视口变换是为了控制显示图

关于erlang打包升级相关文档汇总

如果你需要了解erlang的打包升级,请参考一下文档. System PrinciplesUser's Guide:一篇关于erlang创建目标系统和升级系统相关的官方文档. http://www.erlang.org/doc/system_principles/system_principles.html 中文翻译:http://blog.sina.com.cn/s/blog_96b8a154010128dq.html sasl application是关于erlang打包升级的库 http:

《逐梦旅程 WINDOWS游戏编程之从零开始》笔记8——光照与材质

第14章 绘制出质感的世界--光照与材质 1. 光照与光源 在Direct3D中的光源类型和光照类型是不同的两个概念,光照模型描述的是光线的反射特征,而光源类型主要强调的是能够产生这些光照模型的方式以及光线的位置,方向,强度等特征. 四大光照类型 环境光:基于整个自然界环境的整体亮度,称为环境光或者背景光,没有位置或者方向上的特征,只有一个颜色亮度值,不会衰减,在所有方向和所有物体表面上投射的环境光的数量是恒定不变的(有点像我们白天的自然光).在Direc3D中设置环境光可以直接使用setRen

《Linux就是这个范儿》

<Linux就是这个范儿> 基本信息 作者: 赵鑫磊    (加)Jie Zhang(张洁) 丛书名: 图灵原创 出版社:人民邮电出版社 ISBN:9787115359360 上架时间:2014-6-27 出版日期:2014 年7月 开本:16开 页码:728 版次:1-1 所属分类:计算机 > 操作系统 > Linux 更多关于>>> <Linux就是这个范儿>   编辑推荐 阿里巴巴Linux技术大拿赵鑫磊.支付宝高级专家Jie Zhang带你深入