event_base02

来源:互联网 发布:辣妈拾宝 淘宝达人 编辑:程序博客网 时间:2024/06/17 08:54

出处:http://m.blog.csdn.net/huangjh2017/article/details/78045985

1. 简介

上一节中,我们学习了如何创建一个默认的event_base。但是在实际的应用中,默认的event_base是远远满足不了需求的。更多的时候我们是需要根据具体的使用情况,来建立一个复杂的event_base。关于如何建立复杂的event_base,其实在上一篇章中,我们已经提及。接下来我们将更深入的了解如何建立一个复杂的event_base。

2. event_base_new_with_config

建立一个复杂的event_base需要将设置好的event_config传递给event_base_new_with_config,该函数返回我们所需要的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_MODEevent_debug_mode_too_late = 1;#endif//调用内存管理函数分配event_base结构if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL) {event_warn("%s: calloc", __func__);return NULL;}if (cfg)base->flags = cfg->flags;//设置flags标志//判断是否需要检查EVENT_ * 环境变量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;base->sig.ev_signal_pair[1] = -1;//初始化socketpair,用于唤醒event_base通过其他线程base->th_notify_fd[0] = -1;base->th_notify_fd[1] = -1;//初始化队列TAILQ_INIT(&base->active_later_queue);evmap_io_initmap_(&base->io);evmap_signal_initmap_(&base->sigmap);event_changelist_init_(&base->changelist);base->evbase = NULL;//下面的这操作用于根据event_config进行设定if (cfg) {memcpy(&base->max_dispatch_time,    &cfg->max_dispatch_interval, sizeof(struct timeval));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++) {//根据event_config的配置,是否屏蔽某些后端或设置某项特征if (cfg != NULL) {/* determine if this backend should be avoided */if (event_config_is_avoided_method(cfg,eventops[i]->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];base->evbase = base->evsel->init(base);}//没找到可使用的后端,返回 NULLif (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#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, 0);EVTHREAD_ALLOC_COND(base->current_event_cond);//用于初始化通知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 _WIN32if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP))event_base_start_iocp_(base, cfg->n_cpus_hint);#endifreturn (base);}


2.1 evutil_configure_monotonic_time_

这个函数是用来配置使用时间精度精准或比较粗糙。通过是否设置了使用精准的时间标志选择。
intevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,    int flags){/* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris.  You need to * check for it at runtime, because some older kernel versions won't * have it working. */#ifdef CLOCK_MONOTONIC_COARSE//内核是否支持CLOCK_MONOTONIC_COARSEconst int precise = flags & EV_MONOT_PRECISE;#endifconst int fallback = flags & EV_MONOT_FALLBACK;struct timespects;#ifdef CLOCK_MONOTONIC_COARSE//关于CLOCK_MONOTONIC_COARSE和POSIX中CLOCK_MONOTONIC类似,只不过是精度比较粗糙的版本if (CLOCK_MONOTONIC_COARSE < 0) {/* Technically speaking, nothing keeps CLOCK_* from being * negative (as far as I know). This check and the one below * make sure that it's safe for us to use -1 as an "unset" * value. */event_errx(1,"I didn't expect CLOCK_MONOTONIC_COARSE to be < 0");}//如果flag设置使用精准的时间,那么是不会调用下面的if (! precise && ! fallback) {if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {base->monotonic_clock = CLOCK_MONOTONIC_COARSE;return 0;}}#endif//CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响,方便用于两个事件的间隔if (!fallback && clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {base->monotonic_clock = CLOCK_MONOTONIC;return 0;}if (CLOCK_MONOTONIC < 0) {event_errx(1,"I didn't expect CLOCK_MONOTONIC to be < 0");}base->monotonic_clock = -1;return 0;}

2.2 gettime

这个函数用于获取一个timeval时间
/** Set 'tp' to the current time according to 'base'.  We must hold the lock * on 'base'.  If there is a cached time, return it.  Otherwise, use * clock_gettime or gettimeofday as appropriate to find out the right time. * Return 0 on success, -1 on failure. */static intgettime(struct event_base *base, struct timeval *tp){//如果使能调试锁,那么会断言event_base是否持有锁,这边要求必须持有锁,没有则断言失败EVENT_BASE_ASSERT_LOCKED(base);//如果时间有了缓存,直接返回。避免过多的时间获取调用if (base->tv_cache.tv_sec) {*tp = base->tv_cache;return (0);}//会根据evutil_configure_monotonic_time_中设置的monotonic_clock 来选择是否//使用gettimeofday或clock_gettime获取得到tpif (evutil_gettime_monotonic_(&base->monotonic_timer, tp) == -1) {return -1;}//宏CLOCK_SYNC_INTERVAL定义为5,这里的意思是5s更新一次libevent内部时间不同(可能使用gettimeofday或clock_gettime)if (base->last_updated_clock_diff + CLOCK_SYNC_INTERVAL    < tp->tv_sec) {struct timeval tv;evutil_gettimeofday(&tv,NULL);evutil_timersub(&tv, tp, &base->tv_clock_diff);base->last_updated_clock_diff = tp->tv_sec;}return 0;}

3. 使用范例

#include <stdio.h>#include <string.h>#include <event2/event-config.h>#include <event2/event.h> //cc -I/usr/local/include -o test main.cpp -L/usr/local/lib -leventint main(void){struct event_base *pBase;struct event_config *pConfig;pConfig = event_config_new();//设置event_base_config_flag:不检测环境变量和使用更精准的定时器event_config_set_flag(pConfig, EVENT_BASE_FLAG_IGNORE_ENV | EVENT_BASE_FLAG_PRECISE_TIMER);//告诉event_base不使用epoll和poll后端方法event_config_avoid_method(pConfig, "epoll");event_config_avoid_method(pConfig, "poll");//对后端的特性进行筛选event_config_require_features(pConfig, EV_FEATURE_FDS);//设置CPU数event_config_set_num_cpus_hint(pConfig, 1);//设置事件优先级相关的event_config_set_max_dispatch_interval(pConfig, NULL, -1, 0);pBase = event_base_new_with_config(pConfig);if (pBase == NULL){fprintf(stderr, "event_base_new_with_config error!\r\n");event_config_free(pConfig);return 0;}const char *pCurrMethod = event_base_get_method(pBase);if (pCurrMethod != NULL)printf("Current method is %s\r\n", pCurrMethod);//do something...event_config_free(pConfig);event_base_dispatch(pBase);event_base_free(pBase);return 0;}
在Linux上运行如下所示:
Current method is select
原创粉丝点击