一、事件状态
libevent有4种事件状态,分别是: initialized、pending、active、persistent。这4种状态的转换关系如下:
1、已初始化(initialized):对应图中的non-pending状态,表示事件已经新建完成,但是还未添加到了libevent 队列中。有 4 种方法可以让事件跳转到此状态:
(1)调用 event_new 函数,返回一个事件对象,或调用 event_assign 赋值一个事件对象。
struct event *event_new(
struct event_base *, evutil_socket_t, short, event_callback_fn, void *);
int event_assign(struct event *,
struct event_base *, evutil_socket_t, short, event_callback_fn, void *);
// 回调函数指针定义
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
(2)pinding 状态的事件调用event_del函数后。
(3)active 状态的事件调用完成(即执行完事件回调函数),若没有定义持久化。
2、待决(pending):此状态表示事件已经位于libevent 队列中,可以随时准备执行。有 4 种方法可以让事件跳转到此状态:
(1)调用 event_add 之后。
(2)active 状态的事件调用完成(即执行完事件回调函数),若定义为持久化。
3、激活(active):此状态表示事件正在执行中,也包括超时事件。这是由 libevent 进行调度的,用户也可以手动调用 event_active 函数让事件转为此状态。
4、持久的(persistent):
(1)若定义为持久化,事件完成后状态会由 active 变为 pending ,可仍由 libevent 调用,不用做其他操作;
(2)若未定义为持久化,则表示事件完成后状态会由 active 变为 non-pending ,即初始化状态(initialized)。此时需要再次调用 event_add 函数,将事件变为 pending 状态,事件才会再次被执行。
二、例子
1、下面我们来看一个完整的例子 test_signal.cpp:
#include <iostream>
#include <string.h>
#include <signal.h>
#include <event2/event.h>
#include <event2/listener.h>
#define PORT 5001
using namespace std;
//socket 文件描述符
//which 事件类型
//arg 传递的参数
static void Ctrl_C(int socket, short which, void* arg){
cout<<"Ctrl_C"<<endl;
}
int main()
{
//创建libevent上下文
event_base* base = event_base_new();
if (base) {
cout<<"event_base_new success!"<<endl;
}
//添加ctrl +c信号事件,处于no_pending状态
event *csig = evsignal_new(base, SIGINT, Ctrl_C, base);
if(!csig){
cerr<<"evsignal_new failed!"<<endl;
return -1;
}
//添加事件到pending
if(event_add(csig, 0) != 0){
cerr <<"event_add failed!"<< endl;
return -1;
}
//事件分发处理
if (base) {
event_base_dispatch(base);
}
if (csig) {
event_free(csig);
}
if (base) {
event_base_free(base);
}
return 0;
}
运行结果如下:
2、下面我们把这个例子再深化一下,添加下其他event:
#include <iostream>
#include <string.h>
#include <signal.h>
#include <event2/event.h>
#include <event2/listener.h>
#define PORT 5001
using namespace std;
//socket 文件描述符
//which 事件类型
//arg 传递的参数
static void Ctrl_C(int socket, short which, void* arg){
cout<<"Ctrl_C"<<endl;
}
static void Kill(int socket, short which, void* arg){
cout<<"Kill"<<endl;
//加上下面这段代码后,event又变被重新pending
event* ev = (event*)arg;
if(!evsignal_pending(ev, NULL)){
event_del(ev);
event_add(ev, NULL);
}
}
int main()
{
//创建libevent上下文
event_base* base = event_base_new();
if (base) {
cout<<"event_base_new success!"<<endl;
}
//添加ctrl +c信号事件,处于no_pending状态
//evsignal_new隐藏的状态: EV_SIGNAL|EV_PERSIST
event *csig = evsignal_new(base, SIGINT, Ctrl_C, base);
if(!csig){
cerr<<"evsignal_new csig failed!"<<endl;
return -1;
}
//添加事件到pending
if(event_add(csig, 0) != 0){
cerr <<"event_add csig failed!"<< endl;
return -1;
}
//添加kill信号
//EV_SIGNAL: 没有添加EV_PERSIST,表面当前event为非持久化事件,只能执行1次
//event_self_cbarg(): 传递当前的event
event *ksig = event_new(base, SIGTERM, EV_SIGNAL, Kill, event_self_cbarg());
if(!ksig){
cerr<<"event_new ksig failed!"<<endl;
return -1;
}
//添加事件到pending
if(event_add(ksig, 0) != 0){
cerr <<"event_add ksig failed!"<< endl;
return -1;
}
//事件分发处理
if (base) {
event_base_dispatch(base);
}
if (csig) {
event_free(csig);
}
if (base) {
event_base_free(base);
}
return 0;
}
执行结果如下:
参考:
Libevent 学习四:事件状态和事件处理
https://blog.csdn.net/myw31415926/article/details/127372808