我有一个问题,关于什么在strand
中运行,什么不是。我已经阅读了SO的帖子以及strand
的文档,但是我想确保我已经正确理解了以下代码。
下面的类是一个tcp
客户端,它异步地将内容发送给关心的人。
我还想提到io_service::run
已在多个threads
上调用。
int main( )
{
/* Other stuff */
client.WriteAsync( buffer1 );
client.WriteAsync( buffer2 );
}
/* TcpClient class */
void TcpClient::WriteAsync( std::shared_ptr<boost::asio::streambuf> buffer )
{
// 1
_strand.post( [ this, buffer ]( )
{
_outbuffer.push( buffer );
if ( _outbuffer.size( ) > 1 ) return;
// 2
Write( );
} );
}
void TcpClient::Write( )
{
// 3
boost::asio::async_write( _socket,
*_outbuffer.front( ),
// 4
[ this ]( boost::system::error_code const& error,
size_t const bytesTransferred )
{
_outbuffer.pop( );
if ( error )
{
std::cout << "Error writing: " << error.message( ) << std::endl;
}
if ( !_outbuffer.empty( ) )
{
// 5
Write( );
}
} );
}
1:调用
_strand.post
,如果当前没有任何运行,则strand
将调度传入的处理程序。在这种情况下,传递给该链的lambda
将在该链中执行。如果已经完成工作,则处理程序将排队。2:
Write
,当从传递给lambda
的post
中调用时,在strand
中运行3:在
async_write
中调用strand
。如果async_write
尚未完成,则strand
将不会调度下一个处理程序。4:
async_write
完成处理程序未在strand
中运行。调用async_write
完成处理程序时,strand
将弹出其下一个工作单元并进行调度。5:
Write
从async_write
完成处理程序中调用,并且不在strand
中运行我想知道我的上述说法是否正确。
最佳答案
1:调用_strand.post,如果当前没有任何运行,则strand将分派传入的处理程序。在这种情况下,传递给链的lambda将在链中执行。如果已经完成工作,则处理程序将排队。
正确。
2:写,当从lambda内部调用传递到post时,它在链中运行
正确。
3:在子链中调用async_write。如果async_write尚未完成,则该链将不会调度下一个处理程序。
不正确当传递给链的lambda“返回”时,将运行链工作的下一个排队位。
4:async_write完成处理程序不在链中运行。
正确
调用async_write完成处理程序时,该链将弹出队列中的下一个工作单元,并将其分派。
同样,不正确的是,当传递给链的lambda“返回”时,运行链的下一个排队位。
5:在async_write完成处理程序中调用write,并且未在链中运行
正确。
如果您希望async_write完成处理程序在子程序段中运行(由于对_outbuffer的共享访问,您很可能这样做),则可以使用bind_executor。
例如
void TcpClient::Write( )
{
boost::asio::async_write( _socket,
*_outbuffer.front( ),
// here
boost::asio::bind_executor(_strand, [ this ]( boost::system::error_code const& error, size_t const bytesTransferred )
{
_outbuffer.pop( );
if ( error )
{
std::cout << "Error writing: " << error.message( ) << std::endl;
}
if ( !_outbuffer.empty( ) )
{
// 5
Write( );
}
} ));
}