2016-06-20 7 views
2

私はこのような出力のcointainer有する:複数のスレッド

struct cont { 
    std::mutex m; 
    size_t offset; 
    char* data; 

    cont(size_t sizeB) { 
     data = new char[sizeB]; 
    } 

    void write(char* data, size_t sizeB) { 
     m.lock(); 
     size_t off = offset; 
     offset += sizeB; 
     m.unlock(); 
     std::memcpy(this->data + off, data, sizeB); 
    } 
}; 

を考えは、それぞれ動的にサイズワークロードに作業しない特定の順序でデータを出力し、私は多くのスレッドを有することですその容器に入れる。スレッドはサーバーアクセスによってトリガーされ、同時にどれくらいの数が出ているか、どれくらい貢献するかは分かりません。

これは、理論的には使用可能なバッファの分布のみを同期させる必要があるため、スレッドがその後に衝突してはならないため、メインワークロードはミューテックスロック外にあるからですビット。

これまではうまくいきましたが、これまでの経験から、スレッディングの問題が発生する可能性があるので、これはスレッドセーフな方法と考えられますか?

+1

このバッファから何かが読み込まれますか?バッファがいっぱいになるとどうなりますか? –

+4

唯一の共有メモリは保護されている 'offset'なので、デストラクタでデータを削除する必要はありません。 –

+0

必要なのは、正しく実装され、スレッドセーフ*キュー*です。 – EJP

答えて

0

これは完全に安全だと思われます。おそらく、オフセットが4バイトまたは8バイトの倍数でない数だけ変化したときに、「残された」バイトの並行処理が同時に起こることを心配しているでしょう。私は、標準を引用してあなたの懸念を軽減したいと思いますが、memcpyのエントリはCライブラリリファレンスを指しています。これは細部には及ばないものです。それにもかかわらず、この関数はバッファをunsigned charの配列として扱いますので、境界外のアクセスや不完全なワードの場合には、テールのコピーを最適化することはできません。

2

と思われます。最適化したい場合は、オフセットをアトミックにして、ミューテックスを完全に避けることができます。したがって、宣言するだけです

std::atomic<size_t> offset; 

mutexを削除することができます。

1

これは未完成ですが、ソリューションが複数のスレッド間にスペースを正しく割り当てるだけでなく、スレッドが書き込みを「コミット」するソリューションも必要です。 1つのwriterスレッドがmemcpyの中で(またはそのmemcpyを開始する前に)無限に遅れているとします。どのように他のスレッドがこれについて知っているので、最終的にこのバッファを使うことができますか?

+0

これは、複数のライターで最も難しいビットです。 –

+0

バッファが完全に役立つだけの場合は、すべてのスレッド/ワーカーが何かをしようとする前に(正常に)終了するのを待つことができます。 – ZaldronGG

+0

バッファが常に満たされている場合、関数のreserve()/ commit()、またはそれらの行に沿ったものを持つことによって、memcpyを避けることができます。ワーカースレッドは、バッファに直接書き込む部分を取得し、完了したことを通知します。 –

関連する問題