1

ソケット通信クラスを持つ C++ プログラムがあります。各ソケットには、出力メッセージを組み立てるための大きな専用バッファーがあるため、使用法は次のようになります。

class CSocketClass {
public:
    SetMsgHeader(int n) { Mutex_.lock(); DoWhateverIsNeededToSetHeaderInBuffer(n); } // where n would be the message type
    SetMsgField(double a); { DoWhateverIsNeededToSetDataInBuffer(a); } // where a would be some arbitrary content
    SendMsg(); { DoWhateverIsNeededToSendBuffer(); Mutex_.unlock(); } // where this would send the number of bytes added to the buffer since the   header was set
private:
    char buffer[reallylarge];
    MiscSocketApparatus... 
    boost::mutex   Mutex_;  
};

複数のスレッドがメッセージを送信しようとしている可能性があります。各スレッドは、ヘッダー、コンテンツを設定し、最後に途中でメッセージを送信する 3 つ以上の呼び出しで構成されています。それらが競合しないようにするために、Mutex を使用して、一度に 1 つのライターのみを維持しようとしました。望ましい動作は、最初に到着したライターがミューテックスのロックを解除するまで、2 番目に到着したライターをブロックすることです。その後、ブロックされたライターは続行できます。

これはほとんどの場合うまくいくようですが、まれに (毎日ではありません)、デッドロックが発生することがあります。

私は、スコープ付きロックを使用した単純なロックの問題に精通していますが、これらの概念は、ロックを所有するオブジェクトへの多数の呼び出しにわたってロックを永続化する必要があるこの問題に完全に変換されない場合があります。

Boost Synchronication チュートリアルを読むと、これを行うためのより良い方法があると思いますが、何が最適かは明確ではありません。

任意の推奨事項をいただければ幸いです。

4

1 に答える 1

0

各スレッドには独自のバッファーがあるため、それぞれのバッファーに完全なメッセージを作成してから、ミューテックスロックしてメッセージを送信します。

さらに良いのは、メッセージを実際にディスパッチするスレッドを 1 つ、メッセージを作成するスレッドを N 個用意することです。スレッドセーフなキューを間に入れて、スレッドがメッセージを作成し、それをキューに入れ、(必要に応じて) 別のメッセージの作成に戻ります。メッセージ送信者は、常にキュー内のメッセージを待ち、取得し、送信し、繰り返すだけです。

おそらく、スレッドセーフなバッファーのコレクションも必要になるでしょう。そのため、メッセージが送信されると、送信スレッドは、必要に応じてメッセージビルダースレッドが再び使用できるバッファーを配置できます。

余談ですが、バッファには生配列の代わりにanstd::stringまたは aを使用します。std::vector

于 2013-09-05T03:01:12.533 に答える