我对在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
的{{1}}中被调用时正在post
3::strand
在async_write
中被调用。如果strand
尚未完成,async_write
将不会调度下一个处理程序。
4 :strand
完成处理程序未在async_write
中运行。调用strand
完成处理程序时,async_write
会将下一工作单元弹出队列并进行调度。
5::strand
是从Write
完成处理程序中调用的,并且不是在async_write
我想知道我的上述说法是否正确。
答案 0 :(得分:1)
1:调用_strand.post,如果当前没有任何运行,则strand将分派传入的处理程序。在这种情况下,传递给链的lambda将在链中执行。如果已经完成工作,则处理程序将排队。
正确。
2:写,当从传递给post的lambda内部调用时,在链中运行
正确。
3:在该链中调用async_write。如果async_write尚未完成,则该链将不会调度下一个处理程序。
不正确。当传递给链的lambda“返回”时,将运行下一个排队的链作业。
4:async_write完成处理程序未在链中运行。
正确
调用async_write完成处理程序时,该链将弹出队列中的下一个工作单元,并将其分派。
再次不正确,当传递给链的lambda“返回”时,运行链的下一个排队位。
5:从async_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( );
}
} ));
}