C のマルチライター スレッドセーフ キュー

確かに、ロックレス キューがあります。ただし、コメントで述べたことに基づいて、書き込みごとにスレッドを作成しているため、ここでのパフォーマンスはまったく重要ではありません。

したがって、これは条件変数の標準的な使用例です。ミューテックス、条件変数、リンク リスト (または必要に応じて循環バッファー)、およびキャンセル フラグを含む構造体を作成します。

write:
    lock the mutex
    (optionally - check the cancel flag to prevent leaks of stuff on the list)
    add the event to the list
    signal the condition variable
    unlock the mutex

read:
   lock the mutex
   while (list is empty AND cancel is false):
       wait on the condition variable with the mutex
   if cancel is false:  // or "if list non-empty", depending on cancel semantics
       remove an event from the list
   unlock the mutex
   return event if we have one, else NULL meaning "cancelled"

cancel:
   lock the mutex
   set the cancel flag
   (optionally - dispose of anything on the list, since the reader will quit)
   signal the condition variable
   unlock the mutex

外部ノードでリストを使用している場合は、保持時間を短縮するために、mutex ロックの外側にメモリを割り当てたい場合があります。しかし、侵入型のリスト ノードを使用してイベントを設計すると、おそらく最も簡単です。

編集:キャンセル時に「シグナル」を「ブロードキャスト」に変更すると、複数のリーダーをサポートすることもできます(特定のイベントを取得するポータブル保証はありません)。必要ありませんが、費用もかかりません。


ロックのないキューが必要ない場合は、既存のキューをロックでラップすることができます。

Mutex myQueueLock;
Queue myQueue; 
void mtQueuePush(int value)
{
    lock(myQueueLock);
    queuePush(myQueue, value);
    unlock(myQueueLock);
}
int mtQueueNext()
{
    lock(myQueueLock);
    int value = queueFront(myQueue);
    queuePop(myQueue);
    unlock(myQueueLock);
    return value;
}

後は、キューが空のときに mtQueueNext に何らかの処理を追加するだけです。

編集:単一のリーダー、単一のライターのロックレス キューがある場合、mtQueuePush の周りにロックを設定するだけで、複数の同時ライターを防ぐことができます。

単一のリーダー/ライター ロックレス キューは数多くありますが、そのほとんどは C++ テンプレート クラスとして実装されています。ただし、Google 検索を行い、必要に応じてそれらをプレーンな C で書き直す方法を見つけてください。


http://www.liblfds.org

C で書かれたロックフリーのデータ構造ライブラリ。

M&S キューがあります。