複数の 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.

流れ

  1. struct event_base 型のポインタに、event_init() の戻り値を代入する
  2. struct event 型に、event_set() する
  3. event_base_set() する
  4. event_add() する
  5. 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