2011-10-04 13 views
8

私は現在、libeventを使ってマルチスレッドアプリケーションを書いています。libeventのユーザトリガイベント

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

イベントがevent_new(使用して作成される)、および-1にFDセット:

私は私の問題がどこにあるかを示す簡単なプログラムを書くことを試みました。

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-年使用したくないしタイムアウトを回避策として使用します。だから、これがユーザーが誘発するイベントを使用する正しい方法でない場合は、どうやってそれが行われているか知りたいと思います。

答えて

8

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

追加イベントが必要な場合: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()に新しいフラグを追加するパッチがありますイベント。パッチはover on Githubです。主にコードレビューとそのオプションのより良い名前を待っています。

+0

あなたの素早い返信のためのニックありがとうございます。 – Quentin

+0

私はこれに関するいくつかのコメントを持っています: - 私の現在のプロジェクトについては、私はイベントループを少し使い方を変えて、これを回避して、実際に(不必要に) 1秒はサーバ世界の永遠です)。 - fdまたはタイムアウトのイベントの上で、純粋なユーザートリガーイベントを使用できるようにするのはなぜですか? - イベントが無視される場合、event_addは0以外の何かを返しませんか? 私はevent_base_add_virtualトリックに誘惑されましたが、自分のコードがより新しいバージョンと互換性があります。 – Quentin

+2

純粋なユーザートリガーイベントを使用することができます。event_new(base、-1/* no fd * /、0/*イベントなし*、コールバック、callback_data)でイベントを作成します。 event_active()でそれらをアクティブにします。ただし、event_add()はevent_add()ではありません。event_add()は、ベースがそれ自身のためにポーリングしなければならないイベントに対してのみです。 – nickm

1

私はちょうどlibevent-2.0.21-stableを使用してこれで焼き付きました。それは非常にはっきりとバグです。将来のリリースで修正することを願っています。その間、私たちに警告するためにドキュメントを更新すると便利です。

最良の回避策は、質問に記載されているような偽のタイムアウトのようです。

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

関連する問題