0

I found that asio's doc about synchronization by strand is obscure. It just says that in a thread pool design asio app, the handler can be run in any thread which had call io_service::run(). Using a strand to warp these handler can make their execution concurrent correctly. In its example3, all handle_read are wrap by strand, and I think the variables in Connection class such as buffer has been synchronized by strand, different thread calls handle_read will gets up-to-date data, that is OK. But what about there is a data member defined in Connection class which also accessed by a handler was not wrap by strand? I think this is a problem, isn't it?

In its doc example3, why handle_accept was not wrap by a strand? The new_connection_ is accessed by multi threads: new_connection_.reset called by thread A and server::handle_accept called by thread B. I think it needs data synchronization here or else thread B might use a out-of-date new_connection_ that its reset have not been called yet.

4

2 に答える 2

1

HTTP Server 3は、実際にはstrand.

Boost.Asio の基本的な特性は、ハンドラーが特定の操作に対して最大 1 回呼び出されることです。この動作により、非同期プログラミングの呼び出しパスを、より呼び出しチェーンとして想定することができます。

たとえば、server接続を受け入れるための図解された呼び出しチェーンを調べます。

server::server(...)
{
  start_accept();  --.
}                    |
    .----------------'
    |      .----------------------------------------.
    V      V                                        |
void server::start_accept()                         |
{                                                   |
  new_connection_.reset(new connection(...));       |
  acceptor_.async_accept(..., handle_accept);  --.  |
}                                                |  |
    .--------------------------------------------'  |
    |                                               |
    V                                               |
void server::handle_accept(...)                     |
{                                                   |
  if (!error)                                       |
  {                                                 |
    new_connection_->start();                       |
  }                                                 |    
  start_accept();  ---------------------------------'
}

図に示すように、非同期イベント チェーンは 1 つだけ存在します。でのハンドラーまたは操作の同時実行の可能性がないためnew_connection、暗黙的なストランドで実行されていると言われます。ハンドラserver::handle_acceptが実行されるスレッドは重要ではありません。

呼び出しチェーンとストランドに関するconnection::handle_read詳細は、この質問で回答されています。

于 2013-02-08T15:24:30.670 に答える
1

どういうわけかストランドの意味が欠けていると思います。データ アクセスは同期しません。ハンドラー呼び出しを同期します。これは、「特定のストランドによってラップされたすべてのハンドラーが同時に呼び出されることはない」と理解できます。

したがって、最初の質問: 一部のハンドラーがストランドでラップされていない場合、同時に呼び出すことができます。そのため、同期の問題や RC の対象となります。1 か所にラップしても、RC から保護されているわけではないことに注意してください。これはすべての呼び出しで行う必要があります。ストランドは、使用しない限り、他のスレッドから何を呼び出しているかわかりません.wrap

2 番目の質問: 与えられた例では、 start_acceptが受け入れハンドラー handle_accept を設定し handle_accept新しい受け入れハンドラーを設定しています ( start_acceptの呼び出しを介して)。したがって、2 つ以上のasync_acceptイベントを作成できないため、それらは同時に呼び出されません。確かに、他のスレッドが同じ「サーバー」インスタンスに対してstart_acceptを呼び出した場合、この例は失敗する可能性がありますが、そうするのは明らかな間違いです。

于 2013-02-08T10:04:54.933 に答える