私は最近、boost asio といくつかの新しい c++11 コンストラクトをいじっています。これは、予期しない動作を引き起こすコードのサンプル セクションです (少なくとも私にとっては)。
void Server::startAccept()
{
connections_.push_back(std::make_shared<Connection>(io_service_));
acceptor_.async_accept(connections_.back()->socket(), std::bind(&Server::accept_handler, this, connections_.back(), std::placeholders::_1));
}
void Server::accept_handler(std::shared_ptr<Connection> con, const boost::system::error_code& ec)
{
startAccept();
if (!ec) {
con->start();
}
}
Server::startAccept を呼び出す前に、io_service::work のインスタンスと、io_service_.run() を呼び出す std::thread のプールを作成しました。startAccept を呼び出した後、メイン スレッドはコマンド ライン入力を待つだけです。
スレッド プール内のスレッドの 1 つが、接続の開始時に Server::accept_handler を実行することを期待しています。これは起こりません。代わりに、メイン スレッドから io_service_.run() を呼び出す必要があります。
しばらく遊んでみたところ、これを行うことで目的の動作を実現できることがわかりました。
void Server::startAccept()
{
connections_.push_back(std::make_shared<Connection>(io_service_));
io_service_.post([this]() { acceptor_.async_accept(connections_.back()->socket(), std::bind(&Server::accept_handler, this, connections_.back(), std::placeholders::_1)); });
}
void Server::accept_handler(std::shared_ptr<Connection> con, const boost::system::error_code& ec)
{
startAccept();
if (!ec) {
con->start();
}
}
.async_* 操作と io_service.post の違いは何ですか?
編集: BOOST_ASIO_ENABLE_HANDLER_TRACKING の定義
プログラムをコンパイルして実行し、最初に含めたコード ブロックを使用してサーバーに接続すると、次のような出力が表示されます。
@asio|1350656555.431359|0*1|socket@00A2F710.async_accept
含めた 2 番目のコード ブロックを実行してサーバーに接続すると、次の出力が得られます。
@asio|1350656734.789896|0*1|io_service@00ECEC78.post
@asio|1350656734.789896|>1|
@asio|1350656734.789896|1*2|socket@00D0FDE0.async_accept
@asio|1350656734.789896|<1|
@asio|1350656756.150051|>2|ec=system:0
@asio|1350656756.150051|2*3|io_service@00ECEC78.post
@asio|1350656756.150051|>3|
@asio|1350656756.150051|2*4|socket@00EE9090.async_send
@asio|1350656756.150051|3*5|socket@00D0FDE0.async_accept
@asio|1350656756.150051|2*6|socket@00EE9090.async_receive
@asio|1350656756.150051|<3|
@asio|1350656756.150051|>4|ec=system:0,bytes_transferred=54
@asio|1350656756.150051|<2|
@asio|1350656756.150051|<4|
@asio|1350656758.790803|>6|ec=system:10054,bytes_transferred=0
@asio|1350656758.790803|<6|
編集 2: スレッド作成の洞察
for (int i = 0; i < NUM_WORKERS; i++) {
thread_pool.push_back(std::shared_ptr<std::thread>(new std::thread([this]() { io_service_.run(); })));
}