マルチ プロデューサーと x86 Linux で実行されている単一のコンシューマーを持つリング バッファーのような lmax ディスラプターでコンシューマーが遅い場合の対処法について質問があります。リング バッファ パターンのような lmax を使用すると、常にデータを上書きしますが、消費者が遅い場合はどうなりますか。したがって、たとえば 10 サイズのリング バッファ 0 ~ 9 のリング スロットでコンシューマがスロット 5 にあり、ライターがバッファのスロット 5 でもあるスロット 15 の書き込みを開始する準備ができている場合をどのように処理しますか (つまり、スロット5 = 15 % 10 )? ライターが入ってきた順にデータを生成し、クライアントが同じ順序でデータを受け取るように、これを処理する一般的な方法は何ですか? それは本当に私の質問です。以下は私の設計に関する詳細であり、問題なく動作しますが、現在この問題を処理する良い方法がありません。
設計仕様
リング バッファーがあり、現在、設計には複数のプロデューサー スレッドと 1 つのコンシューマー スレッドがあります。デザインのこの部分は既存のものであり、現在変更することはできません。ロック フリー リング バッファを使用して、既存のキューイング システムを削除しようとしています。私が持っているものは次のとおりです。
コードは x86 Linux で実行され、ライター用に複数のスレッドが実行され、リーダー用に 1 つのスレッドが実行されます。リーダーとライターは 1 スロット離れて開始するstd::atomic<uint64_t>
ため、リーダーはスロット 0 から開始し、ライターはスロット 1 から開始し、各ライターは最初に、以下に示すfetch_add(1, std::memory_order::memory_order_acq_rel)
呼び出しによってライター シーケンスでアトミックを実行してスロットを要求incrementSequence
し、その後、compare_and_swap ループを使用します。このスロットが利用可能であることをクライアントに知らせるためにリーダー シーケンスを更新するには、 を参照してくださいupdateSequence
。
inline data_type incrementSequence() {
return m_sequence.fetch_add(1,std::memory_order::memory_order_seq_cst);
}
void updateSequence(data_type aOld, data_type aNew) {
while ( !m_sequence.compare_exchange_weak(aOld, aNew, std::memory_order::memory_order_release, std::memory_order_relaxed)
if (sequence() < aNew) {
continue;
}
break;
}
}
inline data_type sequence() const {
return m_sequence.load(std::memory_order::memory_order_acquire);
}