转自:http://www.ittomato.com/?p=45
Anatomy of a watcher
假如我要等待STDIN是否可读,你可以createy一个ev_io的watcher,例如
01 |
static void my_cb ( struct ev_loop *loop, ev_io *w, int revents) |
06 |
ev_break (loop, EVBREAK_ALL); |
09 |
struct ev_loop *loop = ev_default_loop (0); |
12 |
ev_init (&stdin_watcher, my_cb); |
13 |
ev_io_set (&stdin_watcher, STDIN_FILENO, EV_READ); |
14 |
ev_io_start (loop, &stdin_watcher); |
每个watcher结构都必须调用ev_init进行初始化,同时指定一个回调函数。
—————————————————————————————————–
1 |
ev_init (ev_TYPE *watcher, callback) |
当watcher捕捉到event时候,会自动调用回调函数(ev_init的第2个参数)。通过调用ev_io_set可以自定义watcher的属性。
一般初始化一个watcher,只须2步:
3 |
ev_io_set (&w, STDIN_FILENO, EV_READ); |
当然还有更简单的办法,直接调用
1 |
ev_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)); \ |
2 |
ev_io_set ((ev),(fd),(events)); } while (0) |
可见,ev_io_init是个宏,整合了ev_init和ev_io_set的宏,ev_io_init等价于:
2 |
ev_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回调函数:
必须的格式:
1 |
void (*)( struct ev_loop *loop, ev_TYPE *watcher, int revents); |
例如上面简单的回调函数,删除掉watcher,再break出loop循环
1 |
static void my_cb( struct ev_loop *loop, ev_io *w, int revents); |
6 |
ev_break(loop, EVBREAK_ALL); |
—————————————————————————————————–
1 |
ev_TYPE_start (loop, ev_TYPE *watcher) |
只有激活的watcher才能收到事件event,ev_TYPE_start,则是激活watcher的函数,例如,激活io事件:
2 |
ev_TYPE_stop (loop, ev_TYPE *watcher) |
同理,撤销watcher:
2 |
ev_run (loop, ev_TYPE *watcher) |
源代码的声明如下:
1 |
EV_API_DECL void ev_run (EV_P_ int flags EV_CPP (= 0)); |
这代码,还起来有点羞涩难懂!一个函数声明,就用了这么多宏。每个宏代表什么?而且函数的参数竟然没有没有逗号分隔开,是一个参数,还是多个?带着这些问题,我们来一步一步跟进源代码!
05 |
# define EV_API_DECL static |
09 |
# define EV_API_DECL extern |
即,EV_API_DECL 等价于static 或者extern
3 |
# define EV_P struct ev_loop *loop |
即,EV_P_ 等价于struct ev_loop *loop,
即,EV_CPP(x)等价于 x或者空
假设已经定义了EV_API_STATIC,__cplusplus,那么上面ev_run函数
1 |
EV_API_DECL void ev_run (EV_P_ int flags EV_CPP (= 0)); |
等价于:
1 |
static 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
简单的几行代码,使用起来方便快捷!
下一节,再更深入了解上面各个函数的具体实现!