イベント ドリブン アーキテクチャを使用する場合は常に、イベントの完了を報告する単一のメカニズムが必要です。 Linux では、ファイルを使用している場合、select または poll ファミリーから何かを使用する必要があります。つまり、パイプを使用して、ファイルに関連しないすべてのイベントを開始することになります。
編集 :Linux には eventfd と timerfd があります。これらは epoll
に追加できます epoll_wait
から抜け出すために使用されます。 それぞれ、別のスレッドからトリガーされたとき、またはタイマー イベントでトリガーされたとき。
別のオプションがあり、それはシグナルです。 fcntl
を使用できます ファイル記述子がアクティブになったときにシグナルが発行されるように、ファイル記述子を変更します。シグナル ハンドラーは、選択した任意のタイプのキューにファイル準備完了メッセージをプッシュできます。これは、単純なセマフォまたはミューテックス/condvar 駆動型キューの場合があります。 select
を使用しなくなったため /poll
、パイプを使用してファイルベースのメッセージをキューに入れる必要がなくなりました。
健康に関する警告:私はこれを試していません。なぜうまくいかないのかわかりませんが、signal
のパフォーマンスへの影響はよくわかりません。
編集:シグナル ハンドラでミューテックスを操作することは、おそらく非常に悪い考えです。
あなたが言及したこと、pipe()およびlibevent(epollをラップする)を使用して、この正確な問題を解決しました。ワーカー スレッドは、出力キューが空から非空になると、パイプ FD に 1 バイトを書き込みます。これにより、メインの IO スレッドが起動し、ワーカー スレッドの出力を取得できます。これは非常にうまく機能し、実際にはコーディングが非常に簡単です。
あなたは Linux タグを持っているので、これを捨てます:POSIX メッセージ キューはこれをすべて行います。これは、あまり望ましくないクロスプラットフォームの願いではないにしても、あなたの「組み込み」要求を満たすはずです.
スレッドセーフな同期が組み込まれています。キューの読み取り時にワーカー スレッドをブロックすることができます。別の方法として、MQ は mq_notify() を使用して、新しいアイテムがキューに入れられたときに新しいスレッドを生成する (または既存のスレッドにシグナルを送る) ことができます。また、select() を使用するように見えるので、MQ の識別子 (mqd_t) を select でファイル記述子として使用できます。