2012-03-13 13 views
0

プロジェクト:一般的なチャットプログラム。サーバーは複数のクライアントからのテキストを受信し、各入力をすべてのクライアントに送っていなければなりません。これはshared_ptrの適切な使用ですか?

サーバでは、各クライアントにソケットfdとstd :: queueを含む構造体を持たせたいと思います。各構造体はstd :: listにあります。

入力がクライアントソケットから受け取られているので、私は構造体のリストを繰り返し処理し、新しい入力を各クライアント構造体のキューに入れたいと思います。文字列のコピーはすべてのクライアントに掛けたくないので、文字列は新しい[ed]です。しかし、私はまた、文字列への複数のポインタを持つことの頭痛を避けるために、最後に文字列を削除するときを決めることを望みます。

これは共有ポインタの適切な機会ですか?もしそうなら、shared_ptrはキューに入れるたびにインクリメントされ、キューからポップするとインクリメントされますか?

ありがとうございました。

+0

はい、私はそれが 'std :: list'の適切な使用ではないと思います。 'ベクトル' FTW! :) –

+0

@Billy ONeal - なぜベクターですか? OPの選択肢は、接続が絶えず追加され削除されているものにとっては良いようです。 – Duck

+1

@Duck: 'std :: list'は局所性が悪く、一般的に数回余分なコピー以上のパフォーマンスを傷つけます。 –

答えて

2

これは、shared_ptrの適切な使用です。そして、新しい、shared_ptrがプッシュするために作成されるので、はい、使用カウントは増分になります。

+0

私がしているかどうかを確認するには:rawPtr = new string; shared_ptr(生);プッシュ(shared_ptr); ...その時点でrefcnt 1または2ですか? 2の場合は、ポップアップした後に実際に削除されてから、範囲外になります。 Plsは上記の構文を見落とし、私はただの概念を模索しています。 –

+0

同じ 'shared_ptr'を複数回プッシュしてスコープ外に出ると、カウントはプッシュの回数になります。 (*同じ* 'shared_ptr'のコピーを必ずプッシュしてください) –

4

これは、疑似ガベージコレクタシステムが参照カウントよりもはるかに優れている場合です。

文字列のリストは1つだけ必要です。なぜなら、すべてのクライアントにすべての入力をファンするからです。一方の端に追加して他方から削除するので、dequeは適切なデータ構造です。

ここで、各接続では、送信した最後の文字列のインデックスを追跡するだけで済みます。定期的に(1000番目のメッセージが受信されるたびに、または4MBが受信されるたびに、またはそのようなもの)、すべてのクライアントでこのインデックスの最小値が見つけられ、そのポイントまで文字列が削除されます。この定期的なチェックは、遠く離れた(接続が切断されている可能性がある)クライアントを検出して回復する機会でもあります。このチェックを行わないと、1つのスタックされたクライアントがプログラムのメモリリークを引き起こします(参照カウント方式であっても)。

このスキームは参照カウントよりも数倍少ないデータであり、キャッシュ競合の主なポイントの1つを削除します(参照カウントは複数のスレッドから書き込まれる必要があるため、パフォーマンスが損なわれます)。スレッドを使用していない場合は、まだ高速です。

+0

それについて考える面白い方法です。それは遅いクライアントを扱う方法の今後の関心に触れます。私はこれについて考える必要があります。ありがとうございました。 –

+0

特に、あるクライアントにメッセージを送信する必要がある場合は、そのメッセージを別のキューに保存するだけです。 –

関連する問題