11

現在、libevent を使用してマルチスレッド アプリケーションを作成しています。

一部のイベントは IO によってトリガーされますが、event_active() を使用して、コード自体によってスレッド全体でトリガーされるイベントがいくつか必要です。

問題がどこにあるかを示す簡単なプログラムを作成しようとしました。

イベントは event_new() を使用して作成され、fd は -1 に設定されます。

event_add() を呼び出すときにタイムアウト構造体が使用されている場合、イベントは後で event_base_dispatch によって適切に処理されます。

代わりに event_add(ev, NULL) を使用すると、0 (明らかに成功) が返されますが、event_base_dispatch() は 1 を返します (これは、イベントが適切に登録されなかったことを意味します)。

この動作は、次のコードを使用して event_add 行を入れ替えてテストできます。

#include <event2/event.h>
#include <unistd.h>

void cb_func (evutil_socket_t fd, short flags, void * _param) {
  puts("Callback function called!");
}

void run_base_with_ticks(struct event_base *base)
{
  struct timeval one_sec;

  one_sec.tv_sec = 1;
  one_sec.tv_usec = 0;
  struct event * ev1;
  ev1 = event_new(base, -1, EV_PERSIST, cb_func, NULL);
  //int result = event_add(ev1, NULL);
  int result = event_add(ev1, &one_sec);
  printf("event_add result: %d\n",result);

  while (1) {
     result = event_base_dispatch(base);
     if (result == 1) {
       printf("Failed: event considered as not pending dispite successful event_add\n");
       sleep(1);
     } else {
       puts("Tick");
     }
  }
}

int main () {
  struct event_base *base = event_base_new();
  run_base_with_ticks(base);
  return 0;
}

コンパイル: g++ sample.cc -levent

問題は、タイムアウトは必要なく、回避策として n 年タイムアウトを使用したくないということです。したがって、これがユーザー トリガー イベントの正しい使用方法でない場合は、その方法を知りたいと思います。

4

2 に答える 2

8

あなたのアプローチは健全です。Libevent 2.0 では、event_active() を使用して、別のスレッドからイベントをアクティブ化できます。適切なスレッド ライブラリを使用するように Libevent に指示するために、前もって適切に evthread_use_windows_threads() または evthread_use_pthreads() を使用していることを確認してください。

追加のイベントが必要な場合: Libevent 2.0 以前では、保留中のイベントが追加されていない場合、イベント ループはすぐに終了します。あなたの最善の策は、おそらくあなたが発見したタイムアウトのトリックです。

それが気に入らない場合は、内部の「event_base_add_virtual」関数を使用して、仮想イベントがあることを event_base に伝えることができます。ただし、この関数はエクスポートされないため、次のように指定する必要があります。

    void event_base_add_virtual(struct event_base *);
    // ...
    base = event_base_new();
    event_base_add_virtual(base); // keep it from exiting

ただし、これはちょっとしたハックであり、文書化されていない関数を使用しているため、Libevent の新しいバージョンで動作しない場合に備えて注意する必要があります。

最後に、このメソッドは現在役に立ちませんが、Libevent の将来のバージョン (2.1 以降) で保留中のパッチがあり、新しいフラグを event_base_loop() に追加して、ループがイベントから外れているときに終了しないようにします。パッチはGithub で終了しました。主にコードのレビューと、オプションのより良い名前を待っています。

于 2011-10-04T10:54:04.430 に答える
1

私は libevent-2.0.21-stable でこれにやられました。これは明らかにバグです。将来のリリースで修正されることを願っています。それまでの間、ドキュメントを更新して、それについて警告していただけると助かります。

最善の回避策は、質問で説明されているように、偽のタイムアウトのようです。

@nickm、あなたは質問を読んでいません。彼のコード例は、あなたが説明したように event_new() を使用しています。libevent にはバグがあり、NULL タイムアウトを使用すると失敗します (ただし、event_add() を呼び出すと 0 を返します)。

于 2014-04-27T21:10:39.723 に答える