前言:
这两天读Bitcoin代码,不禁感慨作者的强大,代码的精妙不是我这码农虔诚膜拜便能读懂的,更远远谈不上企及。于是默默埋头,回想本屌,工作七年还是个默默无闻不及格的码农,黯然内流~~
C/C++那种非人性化的吐槽:
相信很多童鞋跟本农一样,吃过饭之后就是不想洗碗收拾桌子。那太麻烦了,像我们这样怕麻烦的,吃饭首选快餐。以致于错过了自己做饭的乐趣。C/C++就是这样麻烦的发明,效率高不说,可就是要擦屁股,使用malloc/calloc/new等分配的指针所总是要我们自己去回收,多费事啊,为何他们就不能像java那边智能一点呢。当然C++有智能指针,相比C好多了,可依旧麻烦。绕不开这两种语言的只能含泪硬上了。
闲话少说,进入主题:libevent RAII封装
感兴趣的同学可到如下链接下载查看:https://github.com/feekia/EventServer
只帖一部分,摘Bitcoin的,其他的自己扩展了。
#include
#include
#define MAKE_RAII(type) \
/* deleter */\
struct type##_deleter {\
void operator()(struct type* ob) {\
type##_free(ob);\
}\
};\
/* unique ptr typedef */\
typedef std::unique_ptr 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
#include
#include
#include
#include
#include
#include
#include
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 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 "<
输出:
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.