9

boost::asio のドキュメントを読んでも、いつ asio::strand を使用する必要があるかはまだ明確ではありません。io_service を使用するスレッドが 1 つあるとします。次のようにソケットに書き込むのは安全ですか?

void Connection::write(boost::shared_ptr<string> msg)
{
    _io_service.post(boost::bind(&Connection::_do_write,this,msg));
}

void Connection::_do_write(boost::shared_ptr<string> msg)
{
    if(_write_in_progress)
    {
      _msg_queue.push_back(msg);
    }
    else
    {
      _write_in_progress=true;
      boost::asio::async_write(_socket, boost::asio::buffer(*(msg.get())),
      boost::bind(&Connection::_handle_write,this,
             boost::asio::placeholders::error));
    }
}

void Connection::_handle_write(boost::system::error_code const &error)
{
  if(!error)
  {
    if(!_msg_queue.empty())
    {
          boost::shared_ptr<string> msg=_msg_queue.front();
      _msg_queue.pop_front();
      boost::asio::async_write(_socket, boost::asio::buffer(*(msg.get())),
           boost::bind(&Connection::_handle_write,this,
                   boost::asio::placeholders::error));
        }
    else
    {
      _write_in_progress=false;
    }
  }
}

複数のスレッドが Connection::write(..) を呼び出す場所、または asio::strand を使用する必要がありますか?

4

2 に答える 2

22

簡単な答え: いいえ、この場合は a を使用する必要はありませんstrand

大まかに簡略化すると、io_service関数オブジェクト (ハンドラー) のリストが含まれます。post()サービスで が呼び出されると、ハンドラがリストに追加されます。たとえば、非同期操作が完了するたびに、ハンドラとその引数がリストに追加されます。 io_service::run()ハンドラを次々と実行します。したがってrun()、あなたの場合のように呼び出すスレッドが 1 つしかない場合、同期の問題はなく、strands は必要ありません。複数のスレッドが同じを
呼び出す場合にのみ、複数のハンドラーが同時に実行されます (最大 N 個の同時ハンドラーまでの N スレッド)。それが問題になる場合、たとえば、同じオブジェクトにアクセスする 2 つのハンドラーがキューに同時に存在する可能性がある場合は、. あなたは見ることができますrun()io_servicestrand
strandハンドラーのグループの一種のロックとして。に関連付けられたハンドラをスレッドが実行すると、strandそのハンドラstrandはロックされ、ハンドラの実行後に解放されます。他のスレッドは、 locked に関連付けられていないハンドラのみを実行できますstrand

注意:この説明は単純化しすぎており、技術的に正確ではない可能性がありio_serviceますstrand

于 2013-05-06T11:51:30.703 に答える