4

I'm trying to understand the boost::asio but have some problems with it. In this example, please correct me if I'm wrong.

  1. The message is given by reference to the write() method and by value to do_write(). So I think this is ok, even though the do_write is done by io_service.post, the boost::bind is binding the message by value.

  2. But why is there no mutex for the write_msgs_ queue, since std::deque might move around or copy its elements, if needed and io_service::run has it's own thread, it is not ensured the data is consistent.

  3. Is it not better to do it by pointer. If the messages are to long they have always to be copied by value. But with new and delete they will be created before and deleted after sending. Then I would do the send like so

code

boost::asio::async_write(socket_,
      boost::asio::buffer(*write_msgs_.front().data(),
        write_msgs_.front().length()),
      boost::bind(&chat_client::handle_write, this,
        boost::asio::placeholders::error));
4

1 に答える 1

5

1)正しいことと2)が機能する理由。

メインスレッドとクライアントハンドラスレッド間の同期はメソッドを介して行われるため、ここではミューテックスは必要ありませんio_service::postpost実際には何も実行しませんが、実行するスレッドであるコールバックハンドラーにコールバック(バインドされたメソッド)を追加し、そのようなstd::dequeは実行する1つのスレッドio_service::runによってのみアクセスされます。io_service::run

3)これは、スレッドセーフ、例外安全性、および所有権の問題です。

writeスレッドセーフに関しては、1つのスレッドだけを呼び出した後、ポインタが指す文字列にアクセスすることを100%確認する必要があります。
ここでは、所有権と例外の安全性がより興味深い点です。プレーンポインタのみをdequeに格納したい場合は、例外がスローされた場合に文字列が削除されなくなるため、例外安全性の問題が発生します。この問題を回避するには、スマートポインター(例:std :: unique_ptr)のようなものが必要です。これには、C ++11のmove-semanticsまたはref-countingのオーバーヘッドが追加されるshared_ptrが必要です。最もクリーンな解決策は、C++11移動セマンティクスをプレーン文字列と組み合わせて使用​​することです。バッファを書き込み関数に移動し、さらにハンドラに移動するだけで、コピーが不要で例外安全性が得られるという利点があります。
パフォーマンスとコピーについて説明する前のもう1つのポイントは、これが本当に問題であるかどうかを測定する必要があることと、ネットワークI/Oなどの別の問題によってボトルネックになっていないことです。

于 2013-03-19T11:49:37.373 に答える