2013-05-06 12 views
7

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

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を使用する必要がありますか?

答えて

17

短い回答:いいえ、この場合はstrandを使用する必要はありません。

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

注意:この説明は、過簡素化することが技術的に正確ではありませんが、それはio_serviceで何が起こるかのとstrand Sの基本的な考え方を与えることがあります。

2

Connection::write(...)を呼び出すスレッドの数に関係なく、1つのスレッドのみからio_service::run()を呼び出すと、スレッド内ですべてのイベントハンドラが実行されます。したがって、ハンドラの同時実行はできませんが、安全です。ドキュメントには、implicit strandと記載されています。

一方、複数のスレッドがio_service::run()を呼び出す場合は、ストランドが必要になります。 This答えはより詳細にストランドをカバーしています。

関連する問題