libevent之 C++ RAII封装 定时器

3 篇文章 0 订阅
2 篇文章 0 订阅

前言:

    这两天读Bitcoin代码,不禁感慨作者的强大,代码的精妙不是我这码农虔诚膜拜便能读懂的,更远远谈不上企及。于是默默埋头,回想本屌,工作七年还是个默默无闻不及格的码农,黯然内流~~

C/C++那种非人性化的吐槽:

    相信很多童鞋跟本农一样,吃过饭之后就是不想洗碗收拾桌子。那太麻烦了,像我们这样怕麻烦的,吃饭首选快餐。以致于错过了自己做饭的乐趣。C/C++就是这样麻烦的发明,效率高不说,可就是要擦屁股,使用malloc/calloc/new等分配的指针所总是要我们自己去回收,多费事啊,为何他们就不能像java那边智能一点呢。当然C++有智能指针,相比C好多了,可依旧麻烦。绕不开这两种语言的只能含泪硬上了。

闲话少说,进入主题:libevent RAII封装

感兴趣的同学可到如下链接下载查看:https://github.com/feekia/EventServer

 

    只帖一部分,摘Bitcoin的,其他的自己扩展了。

#include <event2/event.h>
#include <event2/listener.h>
#define MAKE_RAII(type) \
/* deleter */\
struct type##_deleter {\
    void operator()(struct type* ob) {\
        type##_free(ob);\
    }\
};\
/* unique ptr typedef */\
typedef std::unique_ptr<struct type, type##_deleter> raii_##type

MAKE_RAII(event_base);
MAKE_RAII(event);
MAKE_RAII(evconnlistener);

inline raii_event_base obtain_event_base() {
    auto result = raii_event_base(event_base_new());
    if (!result.get())
        throw std::runtime_error("cannot create event_base");
    return result;
}

inline raii_event obtain_event(struct event_base* base, evutil_socket_t s, short events, event_callback_fn cb, void* arg) {
    return raii_event(event_new(base, s, events, cb, arg));
}

inline raii_evconnlistener obtain_evconnlistener(struct event_base *base, evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, int socklen) {
	return raii_evconnlistener(
			evconnlistener_new_bind(base, cb, ptr, flags, backlog, sa, socklen));
}

有这些封装就不用管资源的回收了。

 

实例:

定时器每两秒钟回调一次,循环打印。

#include <memory>
#include <event2/event-config.h>
#include <event2/event.h>
#include <event2/event_struct.h>
#include <event2/util.h>
#include <event2/listener.h>

#include <stdio.h>
#include <iostream>
using namespace std;

#define MAKE_RAII(type) \
/* deleter */\
struct type##_deleter {\
    void operator()(struct type* ob) {\
        type##_free(ob);\
    }\
};\
/* unique ptr typedef */\
typedef std::unique_ptr<struct type, type##_deleter> raii_##type

MAKE_RAII(event_base);
MAKE_RAII(event);
MAKE_RAII(evconnlistener);

inline raii_event_base obtain_event_base() {
    auto result = raii_event_base(event_base_new());
    if (!result.get())
        throw std::runtime_error("cannot create event_base");
    return result;
}

inline raii_event obtain_event(struct event_base* base, evutil_socket_t s, short events, event_callback_fn cb, void* arg) {
    return raii_event(event_new(base, s, events, cb, arg));
}

inline raii_evconnlistener obtain_evconnlistener(struct event_base *base, evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, int socklen) {
	return raii_evconnlistener(
			evconnlistener_new_bind(base, cb, ptr, flags, backlog, sa, socklen));
}

struct timeval lasttime;

static void
timeoutCallback(evutil_socket_t fd, short event, void *arg)
{
	struct timeval newtime, difference;
	struct event *timeout = (struct event *)arg;
	double elapsed;
	struct timeval tv{2,0};

	evutil_gettimeofday(&newtime, NULL);
	evutil_timersub(&newtime, &lasttime, &difference);
	elapsed = difference.tv_sec +
	    (difference.tv_usec / 1.0e6);

	cout << "timeoutCallback called at "<<newtime.tv_sec << elapsed << " seconds elapsed."<<endl;
	lasttime = newtime;


//	evutil_timerclear(&tv);
//	tv.tv_sec = 2;
	event_add(timeout, &tv);

}

int main(int argc, char **argv)
{
	struct timeval tv{2,0};
	int flags;
	flags = EV_PERSIST;

    // Obtain event base
    auto raii_base = obtain_event_base();

    auto raii_event = obtain_event(raii_base.get(), -1, 0, nullptr, nullptr);
	/* Initalize one event */
	event_assign(raii_event.get(), raii_base.get(), -1, flags, timeoutCallback, (void*) raii_event.get());

//	evutil_timerclear(&tv);
//	tv.tv_sec = 2;
	event_add(raii_event.get(), &tv);

	evutil_gettimeofday(&lasttime, NULL);

	event_base_dispatch(raii_base.get());

    return 0;
}

输出:

timeoutCallback called at 15259423982.001 seconds elapsed.
timeoutCallback called at 15259424002.001 seconds elapsed.
timeoutCallback called at 15259424022.001 seconds elapsed.
timeoutCallback called at 15259424042.001 seconds elapsed.
timeoutCallback called at 15259424062.001 seconds elapsed.
timeoutCallback called at 15259424082.001 seconds elapsed.
timeoutCallback called at 15259424102.001 seconds elapsed.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值