libev-简单使用解析

来源:互联网 发布:mac常用应用 编辑:程序博客网 时间:2024/06/06 06:58

转自:http://www.ittomato.com/?p=45

Anatomy of a watcher

假如我要等待STDIN是否可读,你可以createy一个ev_io的watcher,例如

01static void my_cb (struct ev_loop *loop, ev_io *w, int revents)
02{//回调函数
03 
04     ev_io_stop (w);
05 
06     ev_break (loop, EVBREAK_ALL);
07 
08}
09struct ev_loop *loop = ev_default_loop (0);
10//创建io的watcher对象
11ev_io stdin_watcher;
12ev_init (&stdin_watcher, my_cb);
13ev_io_set (&stdin_watcher, STDIN_FILENO, EV_READ);
14ev_io_start (loop, &stdin_watcher);
15ev_run (loop, 0);

每个watcher结构都必须调用ev_init进行初始化,同时指定一个回调函数。

—————————————————————————————————–

1ev_init (ev_TYPE *watcher, callback)

当watcher捕捉到event时候,会自动调用回调函数(ev_init的第2个参数)。通过调用ev_io_set可以自定义watcher的属性。

一般初始化一个watcher,只须2步:

1ev_io w;
2ev_init (&w, my_cb);
3ev_io_set (&w, STDIN_FILENO, EV_READ);

当然还有更简单的办法,直接调用

1ev_io_init(&w, my_cb,stdin_fileno, evread);

查看了ev_io_init的源代码,如下:

1#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); \
2ev_io_set ((ev),(fd),(events)); } while (0)

可见,ev_io_init是个宏,整合了ev_init和ev_io_set的宏,ev_io_init等价于:

1ev_init((ev), (cb));
2ev_io_set((ev), (fd), (events));

其他的ev_TYPE_init()函数的实现也类似ev_io_init(),有兴趣可参考下源代码。(TYPE可以是Timer,child,fork,cleanup等等)。ev_io_set必须在ev_init使用后才可以使用;但是ev_TYPE_set可以在ev_init调用后的任何时候再调用!
—————————————————————————————————–

callback回调函数:

必须的格式:

1void (*)(struct ev_loop *loop, ev_TYPE *watcher, int revents);

例如上面简单的回调函数,删除掉watcher,再break出loop循环

1static void my_cb(struct ev_loop *loop, ev_io *w, int revents);
2{
3 
4       ev_io_stop(w);
5 
6       ev_break(loop, EVBREAK_ALL);
7 
8}

—————————————————————————————————–

1ev_TYPE_start (loop, ev_TYPE *watcher)

只有激活的watcher才能收到事件event,ev_TYPE_start,则是激活watcher的函数,例如,激活io事件:

1ev_io_start(loop, &w);
2ev_TYPE_stop (loop, ev_TYPE *watcher)

同理,撤销watcher:

1ev_io_stop(loop, &w);
2ev_run (loop, ev_TYPE *watcher)

源代码的声明如下:

1EV_API_DECL void ev_run (EV_P_ int flags EV_CPP (= 0));

这代码,还起来有点羞涩难懂!一个函数声明,就用了这么多宏。每个宏代表什么?而且函数的参数竟然没有没有逗号分隔开,是一个参数,还是多个?带着这些问题,我们来一步一步跟进源代码!

01EV_API_DECL
02 
03#ifdef EV_API_STATIC
04 
05# define EV_API_DECL static
06 
07#else
08 
09# define EV_API_DECL extern
10 
11#endif

即,EV_API_DECL 等价于static 或者extern

1EV_P_
2 
3# define EV_P  struct ev_loop *loop            
4 
5# define EV_P_ EV_P,

即,EV_P_ 等价于struct ev_loop *loop,

01EV_CPP
02 
03#ifdef __cplusplus
04 
05# define EV_CPP(x) x
06 
07#else
08 
09# define EV_CPP(x)
10 
11#endif

即,EV_CPP(x)等价于 x或者空
假设已经定义了EV_API_STATIC,__cplusplus,那么上面ev_run函数

1EV_API_DECL void ev_run (EV_P_ int flags EV_CPP (= 0));

等价于:

1static void ev_run(struct ev_loop *loop, int flags=0);

变形剖析后的ev_run函数就符合正常代码规格了!

其他的函数,例如ev_io_start,ev_timer_start等的声明也不外乎用了宏!

libev的库使用了大量的宏定义,本文到目前为止,只简单介绍了:

callback,watcher,ev_io,ev_init,ev_io_set,ev_io_start,ev_run各个函数的简单使用!大致了解了libev库的使用方法

1、声明loop

2、声明watcher

3、声明ev_io

4、初始化ev_init

5、设置ev_io_set,(和步骤4一起调用可用函数ev_io_init()替代)

6、把watcher加入到loop的ev_io_start

7、最后运行ev_run

简单的几行代码,使用起来方便快捷!

下一节,再更深入了解上面各个函数的具体实现!

原创粉丝点击