libev官方例程解析

libev - a high performance full-featured event loop written in C - metacpan.org https://metacpan.org/pod/distribution/EV/libev/ev.pod#NAME

============

// a single header file is required
#include <ev.h>
#include <stdio.h> // for puts

--
// every watcher type has its own typedef'd struct with the name ev_TYPE
@ watcher 为 ev_TYPE 类型 ,ev_TYPE 具体可以分为ev_io 、ev_timer 等
ev_io stdin_watcher;
ev_timer timeout_watcher;
 
 
// all watcher callbacks have a similar signature。this callback is called when data is readable on stdin
@ watcher 具备相同的信号,**当**数据可读时触发回调
static void stdin_cb (EV_P_ ev_io *w, int revents)
{
  puts ("stdin ready");
  // for one-shot events, one must manually stop the watcher with its corresponding stop function.
  @ 对于一次性事件,必须用其 对应的停止函数 手动 停止 watcher
  ev_io_stop (EV_A_ w);
 
  // this causes all nested ev_run's to stop iterating  @ 这会导致所有嵌套的ev_run停止迭代
  ev_break (EV_A_ EVBREAK_ALL);
}



// another callback, this time for a time-out
static void  timeout_cb (EV_P_ ev_timer *w, int revents)
{
  puts ("timeout");
  // this causes the innermost ev_run to stop iterating @ 这导致最里面的ev_run停止迭代
  ev_break (EV_A_ EVBREAK_ONE);
}
 



int main (void)
{
  // use the default event loop unless you have special needs
  struct ev_loop *loop = EV_DEFAULT;
 
  // initialise an io watcher, then start it
  // this one will watch for stdin to become readable
  ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
  ev_io_start (loop, &stdin_watcher);
 
  // initialise a timer watcher, then start it
  // simple non-repeating 5.5 second timeout
  ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
  ev_timer_start (loop, &timeout_watcher);
 
  // now wait for events to arrive
  ev_run (loop, 0);
 
  // break was called, so exit
  return 0;
}

=========================
根据官方文档,以下做一些说明

1、在下面的描述中,watcher名称中的大写TYPE代表观察者类型,例如, ev_TYPE_start可以表示定时器观察器的ev_timer_start和I / O观察器的ev_io_start。观察者是一种不透明的结构,您可以分配并注册以记录您对某些事件的兴趣。 举一个具体的例子,假设您想等待STDIN变得可读,您将为此创建一个ev_io观察器:

static void my_cb (struct ev_loop *loop, ev_io *w, int revents)
{
  ev_io_stop (w);
  ev_break (loop, EVBREAK_ALL);
}
 
struct ev_loop *loop = ev_default_loop (0);
 
ev_io stdin_watcher; 
ev_init (&stdin_watcher, my_cb);
ev_io_set (&stdin_watcher, STDIN_FILENO, EV_READ);
ev_io_start (loop, &stdin_watcher);
 
ev_run (loop, 0);

1)struct ev_loop *loop = ev_default_loop (0);定义并负责分配空间给watcher
2)调用 ev_init (watcher *, callback) 初始化 ,callback 对应回调处理
3)ev_TYPE_set (watcher *, …)宏来配置对应类型的watcher,具体包含了对应的参数;
在一次调用中还有一个结合初始化和设置的宏:ev_TYPE_init (watcher *, callback, …)。
4)ev_TYPE_start (loop, watcher *)启动, ev_TYPE_stop (loop, watcher *) 停止
5)只要watcher在运行中,就不要触碰内部数据,也不要对其初始化或ev_TYPE_set设置
6)每个回调先后接收三个参数,
事件循环指针作为第一个,注册的观察者结构作为第二个,并且接收的事件的比特集作为第三个参数
7)收到的事件通常包括每个事件类型接收一个位(您可以同时接收多个事件)。可能的位掩码是:

EV_READ
EV_WRITE
ev_io观察者中的文件描述符已变得可读和/或可写。

EV_TIMER
该ev_timer观察家已超时。

EV_PERIODIC
该ev_periodic观察家已超时。

EV_SIGNAL
ev_signal观察者中指定的信号已被线程接收。

EV_CHILD
ev_child观察者中指定的pid 已收到状态更改。

EV_STAT
ev_stat观察者中指定的路径以某种方式改变了其属性。

EV_IDLE
该ev_idle观察家已经确定,你有什么好做。

EV_PREPARE
EV_CHECK
所有ev_prepare观察者在 ev_run开始收集新事件之前被调用,并且所有ev_check观察者在ev_run收集它们之后排队(未调用),但在排队任何接收事件的任何回调之前。这意味着ev_prepare观察者是在事件循环休眠或轮询新事件之前调用的最后观察者,并且ev_check在事件循环迭代中任何其他具有相同或较低优先级的观察者之前将调用观察者。

两种观察者类型的回调可以像他们想要的那样开始和停止许多观察者,并且所有观察者都将被考虑在内(例如,ev_prepare观察者可能启动空闲观察者以防止ev_run阻塞)。

EV_EMBED
ev_embed观察者中指定的嵌入式事件循环需要引起注意。

EV_FORK
fork之后,子进程中的事件循环已恢复(请参阅参考资料ev_fork)。

EV_CLEANUP
事件循环即将被销毁(参见参考资料ev_cleanup)。

EV_ASYNC
已异步通知给定的异步观察器(请参阅参考资料ev_async)。

EV_CUSTOM
libev本身并未发送(或以其他方式使用),但libev用户可以自由地使用它来发信号通知观察者(例如通过ev_feed_event)。

EV_ERROR
发生了未指定的错误,观察者已停止。这可能是因为观察者无法正常启动,因为libev内存不足,发现文件描述符已关闭或任何其他问题。Libev考虑了这些应用程序错误。

你最好通过报告问题并以某种方式应对被拦截的观察者来采取行动。请注意,编写良好的程序不应该收到任何错误,所以当您的观察者收到它时,这通常表示您的程序中存在错误。

Libev通常会发出一些“虚假”事件和一个错误信号,例如它可能表明fd是可读写的,如果你的回调写得很好,它只能尝试操作并处理读取错误( )或写()。但是,这在多线程程序中不起作用,因为fd已经可以关闭并重新用于其他事情,所以要小心。

2、通用的watcher函数
ev_init (ev_TYPE *watcher, callback)
只初始化了通用的部分,对于每种类型,然后需要调用特定于类型的ev_TYPE_set宏来初始化特定于类型的部分。
对应的ev_TYPE_init宏可以一次完成上面两个动作

Example: Initialise an ev_io watcher in two steps.
ev_io w;
ev_init (&w, my_cb);
ev_io_set (&w, STDIN_FILENO, EV_READ);

ev_TYPE_set (ev_TYPE *watcher, [args])

ev_TYPE_init (ev_TYPE *watcher, callback, [args])
此便捷宏将两个ev_init和ev_TYPE_set宏调用都转换为单个调用。这是初始化观察者最方便的方法。当然,同样的限制也适用。

示例:ev_io一步初始化并设置观察程序。
ev_io_init (&w, my_cb, STDIN_FILENO, EV_READ);

ev_TYPE_start (loop, ev_TYPE *watcher)

ev_TYPE_stop (loop, ev_TYPE *watcher)

3、EV_A, EV_A_,EV_P, EV_P_等宏
Libev可以用各种选项编译,其中最基本的选择是EV_MULTIPLICITY。此选项确定(大多数)函数和回调是否具有初始struct ev_loop *参数。为了更容易编写处理任一变体的程序,定义了以下宏:

EV_A, EV_A_
如果需要,则为函数提供循环参数(“ev循环参数”)。EV_A当这是唯一的参数时使用该表单,EV_A_在其他参数跟随时使用。例:

ev_unref (EV_A);
ev_timer_add (EV_A_ watcher);
ev_run (EV_A_ 0);
它假定loop类型的变量struct ev_loop *在范围内,通常由以下宏提供。

EV_P, EV_P_
如果需要,则为函数提供循环参数(“ev循环参数”)。EV_P当这是唯一参数时使用该表单,EV_P_在其他参数跟随时使用。例:

// this is how ev_unref is being declared
static void ev_unref (EV_P);
 
// this is how you can declare your typical callback
static void cb (EV_P_ ev_timer *w, int revents)
它声明了一个loop类型的参数struct ev_loop *,非常适合使用EV_A。
/* support multiple event loops? */
#if EV_MULTIPLICITY
struct ev_loop;
# define EV_P  struct ev_loop *loop               /* a loop as sole parameter in a declaration */
# define EV_P_ EV_P,                              /* a loop as first of multiple parameters */
# define EV_A  loop                               /* a loop as sole argument to a function call */
# define EV_A_ EV_A,                              /* a loop as first of multiple arguments */
# define EV_DEFAULT_UC  ev_default_loop_uc_ ()    /* the default loop, if initialised, as sole arg */
# define EV_DEFAULT_UC_ EV_DEFAULT_UC,            /* the default loop as first of multiple arguments */
# define EV_DEFAULT  ev_default_loop (0)          /* the default loop as sole arg */
# define EV_DEFAULT_ EV_DEFAULT,                  /* the default loop as first of multiple arguments */
#else
# define EV_P void
# define EV_P_
# define EV_A
# define EV_A_
# define EV_DEFAULT
# define EV_DEFAULT_
# define EV_DEFAULT_UC
# define EV_DEFAULT_UC_
# undef EV_EMBED_ENABLE
#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值