event 非正常退出主循环

event_loopbreak 函数

int
event_loopbreak(void)
{
    return (event_base_loopbreak(current_base));
}
int
event_base_loopbreak(struct event_base *event_base)
{
    if (event_base == NULL)
        return (-1);

    event_base->event_break = 1;
    return (0);
}

event_loopbreak就是直接设置event_base中的event_break退出标记.

event_base_loopexit 函数

int
event_base_loopexit(struct event_base *event_base, const struct timeval *tv)
{
    return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
            event_base, tv));
}

哦豁, 又与到了没有见到过大函数event_base_once函数, 不急慢慢来分析.

先来看一下event_once结构

struct event_once {
	struct event ev;    // 事件

	// 回调函数
	void (*cb)(int, short, void *);
	void *arg;  // 回调函数第三个参数
};
/* Schedules an event once */
// 设置一次性的事件回调, 当该事件执行后便删除不再执行
int
event_base_once(struct event_base *base, int fd, short events,
    void (*callback)(int, short, void *), void *arg, const struct timeval *tv)
{
	struct event_once *eonce;
	struct timeval etv;
	int res;

	/* We cannot support signals that just fire once */
	// 不支持信号
	if (events & EV_SIGNAL)
		return (-1);

	// 申请空间
	if ((eonce = calloc(1, sizeof(struct event_once))) == NULL)
		return (-1);

	eonce->cb = callback;
	eonce->arg = arg;

	if (events == EV_TIMEOUT) {
		if (tv == NULL) {
			evutil_timerclear(&etv);
			tv = &etv;
		}

		evtimer_set(&eonce->ev, event_once_cb, eonce);
	} else if (events & (EV_READ|EV_WRITE)) {
		events &= EV_READ|EV_WRITE;
		// 初始化事件, 并设置事件的回调函数都设置为 event_once_cb
		event_set(&eonce->ev, fd, events, event_once_cb, eonce);
	} else {
		/* Bad event combination */
		free(eonce);
		return (-1);
	}

	// 重新设置该事件
	res = event_base_set(base, &eonce->ev);
	if (res == 0)
		// 将时间设置定时
		res = event_add(&eonce->ev, tv);
	if (res != 0) {
		free(eonce);
		return (res);
	}

	return (0);
}

event_base_once其实就是重新设置了一个eonce结构并初始化了结构中的event事件, 默认回调函数设置成event_once_cb, 接着调用event_base_set重新设置事件的反应器(base).

其中涉及到的event_set, event_base_setevent_add在前面都已经分析过了, 忘了可以重新看一下.

/* One-time callback, it deletes itself */
// event_base_once 默认设置的回调函数
static void
event_once_cb(int fd, short events, void *arg)
{
	struct event_once *eonce = arg;

	// 调用事件的回调函数
	(*eonce->cb)(fd, events, eonce->arg);
	free(eonce);
}
static void
event_loopexit_cb(int fd, short what, void *arg)
{
	struct event_base *base = arg;
	base->event_gotterm = 1;
}

然后event_once_cb回调函数调用后还是调用事件本身注册的一个回调函数.

exit与break区别

  1. event_base_loopexit函数告诉event_base在给定时间后停止循环. 如果tv参数为NULL, 则event_base会在没有延迟的情况下停止循环. 如果主循环现在正在执行回调, 则主循环将继续运行回调直到全部运行完后才执行退出.

    event_base_loopbreak函数告诉event_base立即退出主循环. 它与event_base_loopexit(base,NULL)的不同之处在于. 如果主循环当前正在执行回调, 则执行完当前的回调之后就立即退出, 不再执行剩余就绪的事件.

  2. 当没有运行事件循环时event_base_loopexit(base,NULL)event_base_loopbreak(base)的行为会有所不同 : loopexit会调度事件循环的下一个实例, 以便在运行下一轮回调后立即而loopbreak仅停止当前正在运行的循环, 并且如果主循环未运行则无效.

总结

  1. event_base_loopexit 让主循环在给定时间之后停止循环. 如果tv参数为NULL, 主循环会执行完所有就绪事件之后退出.
  2. event_base_loopbreak 立刻退出主循环.
  3. 不同在于 : 如果event_base当前正在执行激活事件的回调, 调用event_base_loopexit是在执行完当前正在处理的事件后立即退出.

你可能感兴趣的:(libevent)