libevent代码阅读(5)——“hello-world.c”之 event_base对象的创建

首先在main函数中,我们调用event_base_new函数来创建一个event_base对象,一个event_base对象就是一个Reactor实例。

event_base_new函数的流程:
1、创建一个config对象
2、把config对象作为参数,调用event_base_new_with_config函数来创建一个event_base对象

3、释放config对象

// 创建一个Reactor实例
struct event_base * event_base_new(void)
{
	struct event_base *base = NULL;

	// 新建实例的配置
	struct event_config *cfg = event_config_new();
	if (cfg) {
		// 使用该配置初始化Reactor实例
		base = event_base_new_with_config(cfg);
		// 释放配置
		event_config_free(cfg);
	}
	return base;
}

创建config对象的流程如下:

// 创建一个被Reactor实例使用的配置对象
struct event_config * event_config_new(void)
{
	struct event_config *cfg = mm_calloc(1, sizeof(*cfg));

	if (cfg == NULL)
		return (NULL);

	TAILQ_INIT(&cfg->entries);

	return (cfg);
}


event_config的定义如下:

struct event_config {
	TAILQ_HEAD(event_configq, event_config_entry) entries;

	// cpu核数
	int n_cpus_hint;
	
	// event的一些特征
	enum event_method_feature require_features;
	
	// event_base的配置标志
	enum event_base_config_flag flags;
};

event_method_feature和event_base_config_flag分别定义如下:

// 事件处理器的方法的特征
enum event_method_feature {
    /** Require an event method that allows edge-triggered events with EV_ET. */
	// 边沿触发(针对epoll)
    EV_FEATURE_ET = 0x01,

    EV_FEATURE_O1 = 0x02,

    /** Require an event method that allows file descriptors as well as
     * sockets. */
    // 允许文件描述符以及套接字
    EV_FEATURE_FDS = 0x04
};

// 配置标志
enum event_base_config_flag {
	// 非阻塞
	EVENT_BASE_FLAG_NOLOCK = 0x01,

	// 忽略环境
	EVENT_BASE_FLAG_IGNORE_ENV = 0x02,

	// 启动IOCP
	EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,

	// 不缓存系统事件
	EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,

	// epoll使用changelist
	EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10
};

最重要的event_base_new_with_config函数用于创建一个event_base对象

// 使用配置创建一个event_base对象
struct event_base *
event_base_new_with_config(const struct event_config *cfg)
{
	int i;
	struct event_base *base;

	// 是否检测环境
	int should_check_environment;

	// 从现在开始不允许设置调试模式
#ifndef _EVENT_DISABLE_DEBUG_MODE
	event_debug_mode_too_late = 1;
#endif

	// 分配内存
	if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL)
	{
		event_warn("%s: calloc", __func__);
		return NULL;
	}

	// 时间检测
	detect_monotonic();

	// 获取时间
	gettime(base, &base->event_tv);

	// 构造小根堆
	min_heap_ctor(&base->timeheap);

	// 初始化事件处理器队列
	TAILQ_INIT(&base->eventqueue);

	// 被信号所使用的管道
	base->sig.ev_signal_pair[0] = -1;
	base->sig.ev_signal_pair[1] = -1;

	// 使用多线程的时候,这两个用于通知
	base->th_notify_fd[0] = -1;
	base->th_notify_fd[1] = -1;

	// 初始化存放延迟回调函数的链表
	event_deferred_cb_queue_init(&base->defer_queue);

	// 通知的回调函数
	base->defer_queue.notify_fn = notify_base_cbq_callback;
	// 通知回调函数的参数
	base->defer_queue.notify_arg = base;

	// 设置标志
	if (cfg)
		base->flags = cfg->flags;
	// 存放 事件以及事件处理器映射关系 的容器的初始化
	evmap_io_initmap(&base->io);

	// 存放 信号值和信号事件之间的映射关系 的容器的初始化
	evmap_signal_initmap(&base->sigmap);

	// 事件变化队列初始化
	event_changelist_init(&base->changelist);

	// 后台的io复用机制
	base->evbase = NULL;

	// 是否需要检测环境变量
	should_check_environment = !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV));

	// 从众多的io复用机制中选择一个最高效的后台io复用机制
	for (i = 0; eventops[i] && !base->evbase; i++)
	{
		// 如果配置不为空,则所选的io复用用机制,必须满足配置的要求
		if (cfg != NULL)
		{
			/* determine if this backend should be avoided */
			// 检测某一个后台io复用机制是否应该被避免使用
			if (event_config_is_avoided_method(cfg,eventops[i]->name))
				continue;

			// 如果某个io复用机制的某些特征不满足所要求的特征,则跳过
			if ((eventops[i]->features & cfg->require_features)!= cfg->require_features)
				continue;
		}

		/* also obey the environment variables */
		// 必须满足环境变量的要求
		if (should_check_environment && event_is_method_disabled(eventops[i]->name))
			continue;

		// 选中了某一个高效的io复用机制
		base->evsel = eventops[i];
		// 初始化
		base->evbase = base->evsel->init(base);
	}

	if (base->evbase == NULL)
	{
		event_warnx("%s: no event mechanism available",
				__func__);
		base->evsel = NULL;
		event_base_free(base);
		return NULL;
	}

	if (evutil_getenv("EVENT_SHOW_METHOD"))
		event_msgx("libevent using: %s", base->evsel->name);

	// 优先级初始化
	/* allocate a single active event queue */
	if (event_base_priority_init(base, 1) < 0)
	{
		event_base_free(base);
		return NULL;
	}

	/* prepare for threading */
	// 支持多线程
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
	if (EVTHREAD_LOCKING_ENABLED() &&
			(!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK)))
	{
		int r;
		// 分配一个锁
		EVTHREAD_ALLOC_LOCK(base->th_base_lock,
				EVTHREAD_LOCKTYPE_RECURSIVE);
		base->defer_queue.lock = base->th_base_lock;
		// 分配一个条件变量
		EVTHREAD_ALLOC_COND(base->current_event_cond);
		// 设置event_base是否可以被通知
		r = evthread_make_base_notifiable(base);
		if (r<0)
		{
			event_warnx("%s: Unable to make base notifiable.", __func__);
			event_base_free(base);
			return NULL;
		}
	}
#endif

#ifdef WIN32
	if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP))
		event_base_start_iocp(base, cfg->n_cpus_hint);
#endif

	return (base);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值