zoukankan      html  css  js  c++  java
  • Libevent源码剖析(三)

    事件集合(struct event_base)

    struct event_base *event_base_new(void)

    其中有很多的函数已经追踪阅读,但是没有展示,设计思想不难,但是代码由于#define的存在,有点复杂。

    Order 0:struct event_base *event_base_new(void)

    struct event_base * event_base_new(void)
    {
            struct event_base *base = NULL;
    	struct event_config *cfg = event_config_new();        //获取一个struct event_config对象
    	if (cfg) {        //如果对象获取成功,根据config对struct event_base对象进行设置,然后free config object
    		base = event_base_new_with_config(cfg);
    		event_config_free(cfg);
    	}
    	return base;
    }
    

    Order 1:struct event_config* event_config_new(void)void event_config_free(struct event_config *cfg)

    struct event_config* event_config_new(void)
    {
    	struct event_config *cfg = mm_calloc(1, sizeof(*cfg));        //从自定义的alloc中分配一块空间用于存放config object
    
    	if (cfg == NULL)        //如果分配失败,返回NULL
    		return (NULL);
    
    	TAILQ_INIT(&cfg->entries);        //初始化config object的双向队列
    	cfg->max_dispatch_interval.tv_sec = -1;        //如果为-1,则在没有事件时陷入等待,直到有事件发生。
    	cfg->max_dispatch_callbacks = INT_MAX;        //将callback的处理限制为INT_MAX
    	cfg->limit_callbacks_after_prio = 1;        //优先级默认为1,就是全局只有这么一个优先级
    
    	return (cfg);
    }
    
    void event_config_free(struct event_config *cfg)
    {
    	struct event_config_entry *entry;        //从config object中逐个取出struct event_config_entry对象(这个对象中没啥实际的东西)并删除
    
    	while ((entry = TAILQ_FIRST(&cfg->entries)) != NULL) {
    		TAILQ_REMOVE(&cfg->entries, entry, next);
    		event_config_entry_free(entry);
    	}
    	mm_free(cfg);        //归还config Object内存
    }
    

    Order 1:struct event_base * event_base_new_with_config(const struct event_config *cfg)

    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) {        //获取存储struct event_base的对象
    		event_warn("%s: calloc", __func__);
    		return NULL;
    	}
    
    	if (cfg)    //根据config对象设置event_base
    		base->flags = cfg->flags;
    
    	should_check_environment =
    	    !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV));        //判断是否需要检查当前环境
    
    	{
    		struct timeval tmp;
    		int precise_time =
    		    cfg && (cfg->flags & EVENT_BASE_FLAG_PRECISE_TIMER);        //检查是否设置了精确时间的选项
    		int flags;
    		if (should_check_environment && !precise_time) {
    			precise_time = evutil_getenv_("EVENT_PRECISE_TIMER") != NULL;
    			base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
    		}
    		flags = precise_time ? EV_MONOT_PRECISE : 0;        //判断是否需要精确时间选项
    		evutil_configure_monotonic_time_(&base->monotonic_timer, flags);        //配置那个为空的对象
    
    		gettime(base, &tmp);        //获取时间
    	}
    
    	min_heap_ctor_(&base->timeheap);        //将超时时间以最小堆组织起来
    
    	base->sig.ev_signal_pair[0] = -1;        //将sockpair处理的事件机制的fd初始化为-1
    	base->sig.ev_signal_pair[1] = -1;
    	base->th_notify_fd[0] = -1;
    	base->th_notify_fd[1] = -1;
    
    	TAILQ_INIT(&base->active_later_queue);        //初始化下一轮循环通知的事件初始化
    
    	evmap_io_initmap_(&base->io);        //初始化IO事件map(HASH)
    	evmap_signal_initmap_(&base->sigmap);        //初始化信号事件(HASH)
    	event_changelist_init_(&base->changelist);        //初始化事件修改链表
    
    	base->evbase = NULL;        //将指向特定数据的指针初始化为NULL
    
    	if (cfg) {
    		memcpy(&base->max_dispatch_time,
    		    &cfg->max_dispatch_interval, sizeof(struct timeval));        //根据config对象,初始化struct event_base的:
    		base->limit_callbacks_after_prio =
    		    cfg->limit_callbacks_after_prio;
    	} else {
    		base->max_dispatch_time.tv_sec = -1;        //事件循环时间
    		base->limit_callbacks_after_prio = 1;        //事件优先级
    	}
    	if (cfg && cfg->max_dispatch_callbacks >= 0) {        //初始化事件处理的最大数量
    		base->max_dispatch_callbacks = cfg->max_dispatch_callbacks;
    	} else {
    		base->max_dispatch_callbacks = INT_MAX;
    	}
    	if (base->max_dispatch_callbacks == INT_MAX &&
    	    base->max_dispatch_time.tv_sec == -1)
    		base->limit_callbacks_after_prio = INT_MAX;        //初始化优先级数量
    
    	for (i = 0; eventops[i] && !base->evbase; i++) {        //eventops是一个全局数据结构,如果全局数据结构存在并且base的私有数据不存在,就执行代码
    		if (cfg != NULL) {        //如果有config object
    			if (event_config_is_avoided_method(cfg,
    				eventops[i]->name))        //将eventop中的name字符串,传递给配置对象
    				continue;
    			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;
    
    		base->evsel = eventops[i];        //将信号处理ops注册给base的信号处理ops
    
    		base->evbase = base->evsel->init(base);        //私有数据 = struct event_base对象??有可能是反向获取struct event_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 */
    
    #if !defined(EVENT__DISABLE_THREAD_SUPPORT) && !defined(EVENT__DISABLE_DEBUG_MODE)
    	event_debug_created_threadable_ctx_ = 1;
    #endif
    
    	if (EVTHREAD_LOCKING_ENABLED() &&
    	    (!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK))) {
    		int r;
    		EVTHREAD_ALLOC_LOCK(base->th_base_lock, 0);        //初始化互斥锁
    		EVTHREAD_ALLOC_COND(base->current_event_cond);        //初始化条件变量
    		r = evthread_make_base_notifiable(base);        //这个函数会初始化与唤醒主线程的sockpair以及注册唤醒主线程的函数,都不难,可以很快用C++实现
    		if (r<0) {
    			event_warnx("%s: Unable to make base notifiable.", __func__);
    			event_base_free(base);
    			return NULL;
    		}
    	}
    
    	return (base);        //返回已经初始化的struct event_base对象
    }
    

    void event_base_free(struct event_base *base)

    Order 0:void event_base_free(struct event_base *base)

    void event_base_free(struct event_base *base)
    {
    	event_base_free_(base, 1);
    }
    

    Order 1:static void event_base_free_(struct event_base *base, int run_finalizers)

    static void event_base_free_(struct event_base *base, int run_finalizers)
    {
    	int i, n_deleted=0;
    	struct event *ev;
    	
    	if (base == NULL && current_base)        //获取现有的struct event_base对象
    		base = current_base;
    
    	if (base == NULL) {
    		event_warnx("%s: no base to free", __func__);
    		return;
    	}
    
    	if (base->th_notify_fd[0] != -1) {        //在事件库中存在多个线程,终止时需要合理的处理这些线程
    		event_del(&base->th_notify);        //从事件队列中删除与多线程通信的事件
    		EVUTIL_CLOSESOCKET(base->th_notify_fd[0]);        //关闭管道fd
    		if (base->th_notify_fd[1] != -1)
    			EVUTIL_CLOSESOCKET(base->th_notify_fd[1]);        //关闭管道fd
    		base->th_notify_fd[0] = -1;
    		base->th_notify_fd[1] = -1;
    		event_debug_unassign(&base->th_notify);        //测试这个event是否已经取消注册
    	}
    
    	evmap_delete_all_(base);        //删除事件链表中所有的IO事件与信号事件
    
    	while ((ev = min_heap_top_(&base->timeheap)) != NULL) {        //从最小堆中删除所有的超时事件 
    		event_del(ev);
    		++n_deleted;
    	}
    	for (i = 0; i < base->n_common_timeouts; ++i) {        //这个管理超时事件的common没有搞懂
    		struct common_timeout_list *ctl =
    		    base->common_timeout_queues[i];
    		event_del(&ctl->timeout_event); /* Internal; doesn't count */
    		event_debug_unassign(&ctl->timeout_event);
    		for (ev = TAILQ_FIRST(&ctl->events); ev; ) {
    			struct event *next = TAILQ_NEXT(ev,
    			    ev_timeout_pos.ev_next_with_common_timeout);
    			if (!(ev->ev_flags & EVLIST_INTERNAL)) {
    				event_del(ev);
    				++n_deleted;
    			}
    			ev = next;
    		}
    		mm_free(ctl);
    	}
    	if (base->common_timeout_queues)        //释放公共超时事件队列
    		mm_free(base->common_timeout_queues);
    
    	for (;;) {        //回收处理事件的线程资源
    		int i = event_base_free_queues_(base, run_finalizers);
    		if (!i) {
    			break;
    		}
    		n_deleted += i;
    	}
    
    	if (n_deleted)
    		event_debug(("%s: %d events were still set in base",
    			__func__, n_deleted));
    
    	while (LIST_FIRST(&base->once_events)) {        //从只注册一次的事件,但是事件还没有发生的链表中,逐个删除事件
    		struct event_once *eonce = LIST_FIRST(&base->once_events);
    		LIST_REMOVE(eonce, next_once);
    		mm_free(eonce);
    	}
    
    	if (base->evsel != NULL && base->evsel->dealloc != NULL)
    		base->evsel->dealloc(base);        //使用注册的函数清理base
    
    	for (i = 0; i < base->nactivequeues; ++i)        //在销毁struct event_base对象之前,逐个清理
    		EVUTIL_ASSERT(TAILQ_EMPTY(&base->activequeues[i]));
    
    	EVUTIL_ASSERT(min_heap_empty_(&base->timeheap));        //在销毁之前,确保最小堆已经被清理干净
    	min_heap_dtor_(&base->timeheap);        //销毁最小堆
    
    	mm_free(base->activequeues);        //释放活动事件队列
    
    	evmap_io_clear_(&base->io);        //清理IO事件队列
    	evmap_signal_clear_(&base->sigmap);        //清理信号事件队列
    	event_changelist_freemem_(&base->changelist);        //清理改变事件队列
    
    	EVTHREAD_FREE_LOCK(base->th_base_lock, 0);        //释放锁与条件变量
    	EVTHREAD_FREE_COND(base->current_event_cond);
    
    	if (base == current_base)
    		current_base = NULL;
    	mm_free(base);
    }
    

    int event_reinit(struct event_base *base)

    Order 0:int event_reinit(struct event_base *base)

    int event_reinit(struct event_base *base)
    {
    	const struct eventop *evsel;
    	int res = 0;
    	int was_notifiable = 0;
    	int had_signal_added = 0;
    
    	EVBASE_ACQUIRE_LOCK(base, th_base_lock);        //获取锁
    
    	evsel = base->evsel;        //获取处理事件的ops
    
    	if (evsel->need_reinit) {        //如果struct event_base对象在fork之后需要重新进行处理
    		base->evsel = &nil_eventop;        //获取信号处理
    	}
    
    	if (base->sig.ev_signal_added) {
    		event_del_nolock_(&base->sig.ev_signal, EVENT_DEL_AUTOBLOCK);
    		event_debug_unassign(&base->sig.ev_signal);
    		memset(&base->sig.ev_signal, 0, sizeof(base->sig.ev_signal));
    		had_signal_added = 1;
    		base->sig.ev_signal_added = 0;
    	}
    	if (base->sig.ev_signal_pair[0] != -1)
    		EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]);
    	if (base->sig.ev_signal_pair[1] != -1)
    		EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]);
    	if (base->th_notify_fn != NULL) {
    		was_notifiable = 1;
    		base->th_notify_fn = NULL;
    	}
    	if (base->th_notify_fd[0] != -1) {
    		event_del_nolock_(&base->th_notify, EVENT_DEL_AUTOBLOCK);
    		EVUTIL_CLOSESOCKET(base->th_notify_fd[0]);
    		if (base->th_notify_fd[1] != -1)
    			EVUTIL_CLOSESOCKET(base->th_notify_fd[1]);
    		base->th_notify_fd[0] = -1;
    		base->th_notify_fd[1] = -1;
    		event_debug_unassign(&base->th_notify);
    	}
    
    	/* Replace the original evsel. */
            base->evsel = evsel;
    
    	if (evsel->need_reinit) {
    		/* Reconstruct the backend through brute-force, so that we do
    		 * not share any structures with the parent process. For some
    		 * backends, this is necessary: epoll and kqueue, for
    		 * instance, have events associated with a kernel
    		 * structure. If didn't reinitialize, we'd share that
    		 * structure with the parent process, and any changes made by
    		 * the parent would affect our backend's behavior (and vice
    		 * versa).
    		 */
    		if (base->evsel->dealloc != NULL)
    			base->evsel->dealloc(base);
    		base->evbase = evsel->init(base);
    		if (base->evbase == NULL) {
    			event_errx(1,
    			   "%s: could not reinitialize event mechanism",
    			   __func__);
    			res = -1;
    			goto done;
    		}
    
    		/* Empty out the changelist (if any): we are starting from a
    		 * blank slate. */
    		event_changelist_freemem_(&base->changelist);
    
    		/* Tell the event maps to re-inform the backend about all
    		 * pending events. This will make the signal notification
    		 * event get re-created if necessary. */
    		if (evmap_reinit_(base) < 0)
    			res = -1;
    	} else {
    		res = evsig_init_(base);
    		if (res == 0 && had_signal_added) {
    			res = event_add_nolock_(&base->sig.ev_signal, NULL, 0);
    			if (res == 0)
    				base->sig.ev_signal_added = 1;
    		}
    	}
    
    	/* If we were notifiable before, and nothing just exploded, become
    	 * notifiable again. */
    	if (was_notifiable && res == 0)
    		res = evthread_make_base_notifiable_nolock_(base);
    
    done:
    	EVBASE_RELEASE_LOCK(base, th_base_lock);
    	return (res);
    }
    
  • 相关阅读:
    zoj 1649 Rescue
    poj 1659 Frogs' Neighborhood
    hdu 1385 Minimum Transport Cost
    hdu 2680 Choose the best route
    写了一下午的dijkstra。突然发现我写的根本不是dijkstra。。。。是没优化过的BFS.......
    hdu 1548 A strange lift
    hdu 2066 一个人的旅行
    hdu 2544 最短路
    洛谷 P3253 [JLOI2013]删除物品 解题报告
    洛谷 P10P1343 地震逃生 改错
  • 原文地址:https://www.cnblogs.com/ukernel/p/9191078.html
Copyright © 2011-2022 走看看