複数の event_base を使う場合
libevent で、複数の event_base を使いたい場合、man event を良く読めば、実は書いてあるのですが、
単純な勘違いで、うまくいかない場合があります。
man event 抜粋
THREAD SAFE EVENTS
Libevent has experimental support for thread-safe events. When initial-
izing the library via event_init(), an event base is returned. This
event base can be used in conjunction with calls to event_base_set(),
event_base_dispatch(), event_base_loop(), event_base_loopexit(),
bufferevent_base_set() and event_base_free(). event_base_set() should be
called after preparing an event with event_set(), as event_set() assigns
the provided event to the most recently created event base.
bufferevent_base_set() should be called after preparing a bufferevent
with bufferevent_new(). event_base_free() should be used to free memory
associated with the event base when it is no longer needed.
流れ
- struct event_base 型のポインタに、event_init() の戻り値を代入する
- struct event 型に、event_set() する
- event_base_set() する
- event_add() する
- event_base_dispatch() する
event_base_set() する前に、event_add() してしまうと、event_base_set() が失敗し、
思うように動作しません。
サンプルコード
#include#include
int g_hoge = 0;
struct event_base *g_event_base_1;
struct event_base *g_event_base_2;
struct event_base *g_event_base_3;void
timer_func(int fd, short event, void *arg)
{
struct timeval tv;
struct event *timer = (struct event *) arg;
printf("hoge\n");
if (++g_hoge == 10) {
event_base_loopexit(g_event_base_2, NULL);
}
tv.tv_sec = 0;
tv.tv_usec = 500 * 1000;
evtimer_set(timer, timer_func, timer);
if (event_base_set(g_event_base_2, timer) == -1) {
perror("event_base_set");
}
evtimer_add(timer, &tv);
}int
main(int argc, char *argv[])
{
struct timeval tv;
struct event timer;
tv.tv_sec = 0;
tv.tv_usec = 500 * 1000;
if ( (g_event_base_1 = event_init() ) == NULL) {
perror("g_event_base_1");
}
if ( (g_event_base_2 = event_init() ) == NULL) {
perror("g_event_base_2");
}
if ( (g_event_base_3 = event_init() ) == NULL) {
perror("g_event_base_3");
}
evtimer_set(&timer, timer_func, &timer);
if (event_base_set(g_event_base_2, &timer) == -1) {
perror("event_base_set");
}
evtimer_add(&timer, &tv);
event_base_dispatch(g_event_base_2);
event_base_free(g_event_base_1);
event_base_free(g_event_base_2);
event_base_free(g_event_base_3);
return (0);
}
実行例
このサンプルを動かすと、0.5秒おきに、「hoge」と表示されて、
きちんと、g_event_base_2 のディスパッチが出来ていることが確認できます。
% gcc main.c -levent -I/opt/local/include/ -L/opt/local/lib -o main ; ./main
hoge
hoge
hoge
hoge
hoge
hoge
hoge
hoge
hoge
hoge