Libevent官方代码样例学习(一)
2017-12-05 01:07
357 查看
在Ubuntu16.04中, libevent的默认安装位置为
https://github.com/libevent/libevent/blob/master/sample/time-test.c
这是一个定时触发事件的例子, 根据输入参数的不同, 单次执行或持续执行.
在main方法中, 通过以下的方法调用将timeout_event加入到将来的事件中.
将timeout_event作为参数传入callback方法, 然后在callback方法中再次将timeout_event加入到将来的事件中
在这种情况下, 原代码中的flags = EV_PERSIST其实是不起作用的, 因为callback中复用了原来的内存地址, 设置为flags = 0一样能持续执行.
如果将event_assign改为event_new, 则调用变为
而callback中的处理变为
这时候, 如果代码中使用flags = EV_PERSIST就会产生内存泄漏, 因为在触发后并不释放, 会持续的每隔1秒调用callback, 这时候要么在callback中不新增event, 要么flag设为0.
修改后的代码:
Update 2017-12-05:
如果使用的是libevent 2.1.1以后的版本, 可以使用event_self_cbarg()方法. 在event_new中通过 event_self_cbarg() 方法传入自身指针.
#在 trusty 发行版中 amd64 硬件架构下的 libevent-2.0-5 软件包文件清单 /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5 /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5.1.9 /usr/share/doc/libevent-2.0-5/changelog.Debian.gz /usr/share/doc/libevent-2.0-5/copyright
https://github.com/libevent/libevent/blob/master/sample/time-test.c
这是一个定时触发事件的例子, 根据输入参数的不同, 单次执行或持续执行.
在main方法中, 通过以下的方法调用将timeout_event加入到将来的事件中.
base = event_base_new(); struct event timeout; event_assign(&timeout_event, base, -1, flags, timeout_callback, (void *) &timeout_event); event_add(timeout_event, &tv); event_base_dispatch(base);
将timeout_event作为参数传入callback方法, 然后在callback方法中再次将timeout_event加入到将来的事件中
struct event *timeout_event = arg; // ... event_add(timeout_event, &tv);
在这种情况下, 原代码中的flags = EV_PERSIST其实是不起作用的, 因为callback中复用了原来的内存地址, 设置为flags = 0一样能持续执行.
如果将event_assign改为event_new, 则调用变为
base = event_base_new(); // 注意此处不传入event而传入event_base, 因为event在当前方法中new并alloca空间, 所以传入的event指针是无效的. struct event *timeout_event = event_new(base, -1, flags, timeout_callback, base); event_add(timeout_event, &tv); evutil_gettimeofday(&lasttime, NULL); event_base_dispatch(base);
而callback中的处理变为
struct event_base *base = arg; struct event *timeout_event = event_new(base, -1, 0, timeout_callback, base); event_add(timeout_event, &tv);
这时候, 如果代码中使用flags = EV_PERSIST就会产生内存泄漏, 因为在触发后并不释放, 会持续的每隔1秒调用callback, 这时候要么在callback中不新增event, 要么flag设为0.
修改后的代码:
/* * XXX This sample code was once meant to show how to use the basic Libevent * interfaces, but it never worked on non-Unix platforms, and some of the * interfaces have changed since it was first written. It should probably * be removed or replaced with something better. * * Compile with: * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent */ #include <sys/types.h> #ifndef _WIN32 #include <sys/queue.h> #include <unistd.h> #endif #ifdef EVENT__HAVE_SYS_TIME_H #include <sys/time.h> #endif #include <stdio.h> #include <string.h> #include <event2/event.h> #include <event2/event_struct.h> #ifdef _WIN32 #include <winsock2.h> #endif struct timeval lasttime; int event_is_persistent; static void timeout_callback(evutil_socket_t fd, short event, void *arg) { struct timeval newtime, difference; struct event_base *base = arg; double elapsed; // The evutil_gettimeofday function sets tv to the current time. The second argument is unused. evutil_gettimeofday(&newtime, NULL); // This macro subtract (respectively) their first two arguments, and stores the result in the third. evutil_timersub(&newtime, &lasttime, &difference); elapsed = difference.tv_sec + (difference.tv_usec / 1.0e6); printf("timeout_callback called at %d: %.3f seconds elapsed.\n", (int) newtime.tv_sec, elapsed); lasttime = newtime; if (event_is_persistent == 1) { struct event *timeout_event = event_new(base, -1, 0, timeout_callback, base); struct timeval tv; evutil_timerclear(&tv); tv.tv_sec = 0; tv.tv_usec = 10000; event_add(timeout_event, &tv); } } int main(int argc, char **argv) { struct timeval tv; struct event_base *base; int flags; // strcmp: <0 the first character that does not match has a lower value in ptr1 than in ptr2 // 0 the contents of both strings are equal // >0 the first character that does not match has a greater value in ptr1 than in ptr2 if (argc == 2 && !strcmp(argv[1], "-p")) { event_is_persistent = 1; // Use this if you use event_new instead of event_assign flags = 0; } else { event_is_persistent = 0; flags = 0; } /* Initalize the event library */ base = event_base_new(); /* * Prepare a new, already-allocated event structure to be added. * The function event_assign() prepares the event structure ev to be used in future calls to event_add() and event_del(). * Unlike event_new(), it doesn't allocate memory itself: it requires that you have already allocated a struct event, * probably on the heap. Doing this will typically make your code depend on the size of the event structure, and thereby * create incompatibility with future versions of Libevent. * The easiest way to avoid this problem is just to use event_new() and event_free() instead. * A slightly harder way to future-proof your code is to use event_get_struct_event_size() to determine the required size * of an event at runtime. * Note that it is NOT safe to call this function on an event that is active or pending. Doing so WILL corrupt internal * data structures in Libevent, and lead to strange, hard-to-diagnose bugs. You can use event_assign to change an existing * event, but only if it is not active or pending! */ //event_assign(&timeout_event, base, -1, flags, timeout_callback, (void *) &timeout_event); struct event *timeout_event = event_new(base, -1, flags, timeout_callback, base); // Set (tvp)->tv_sec and (tvp)->tv_usec to 0 evutil_timerclear(&tv); tv.tv_sec = 1; // Add an event to the set of pending events. // The function event_add() schedules the execution of the ev event when the event specified in event_assign()/event_new() occurs, // or when the time specified in timeout has elapesed. If atimeout is NULL, no timeout occurs and the function will only be called // if a matching event occurs. The event in the ev argument must be already initialized by event_assign() or event_new() and may // not be used in calls to event_assign() until it is no longer pending. // If the event in the ev argument already has a scheduled timeout, calling event_add() replaces the old timeout with the new one, // or clears the old timeout if the timeout argument is NULL. event_add(timeout_event, &tv); evutil_gettimeofday(&lasttime, NULL); event_base_dispatch(base); return (0); }
Update 2017-12-05:
如果使用的是libevent 2.1.1以后的版本, 可以使用event_self_cbarg()方法. 在event_new中通过 event_self_cbarg() 方法传入自身指针.
#include <event2/event.h> static int n_calls = 0; void cb_func(evutil_socket_t fd, short what, void *arg){ struct event *me = arg; printf("cb_func called %d times so far.\n", ++n_calls); if (n_calls > 100) event_del(me); } void run(struct event_base *base){ struct timeval one_sec = { 1, 0 }; struct event *ev; /* We're going to set up a repeating timer to get called called 100 times. */ ev = event_new(base, -1, EV_PERSIST, cb_func, event_self_cbarg()); event_add(ev, &one_sec); event_base_dispatch(base); }
相关文章推荐
- Libevent官方代码样例学习(二)
- Libevent学习笔记,异步非阻塞SOCKET,从初等到高等代码
- 学习微信官方代码--简单自动回复
- Libevent 官方文档学习笔记(1. libevent_core部分)
- 【jQuery】jQuery官方基本教程的学习笔记7-代码组织Code Organization
- ios 学习之你画我话绘图四 读取pdf (官方代码)
- Libevent 官方文档学习笔记(2. bufferevent部分)
- 学习微信官方代码wx_sample.php
- 学习微信官方代码---关键字自动回复
- Libevent 官方文档学习笔记(3. evbuffer部分)
- opencv官方样例学习笔记——introduction_to_svm
- linux 下第一个Libevent代码学习
- 学习微信官方代码----连接数据库
- Unity实例.003官方示例Survival Shooter Tutorial核心代码学习
- c语言学习之结构篇代码演示样例-输入n个同学的姓名,数学英语成绩,依照平均分从低到高排序并输出
- libevent官方文档学习笔记
- 【UE4学习】04——官方教程代码
- c语言学习之结构篇代码演示样例-输入n个同学的姓名,数学英语成绩,依照平均分从低到高排序并输出
- 苹果官方示例代码《LazyTableImages》异步加载图片的学习记录
- ASIO官方例子学习1.为服务器异步操作定制内存分配模型代码分析(allocation/server.cpp)