阐明在boost :: strand

时间:2018-08-18 18:20:07

标签: c++ boost boost-asio

我对在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:strandasync_write中被调用。如果strand尚未完成,async_write将不会调度下一个处理程序。

4 strand完成处理程序async_write中运行。调用strand完成处理程序时,async_write会将下一工作单元弹出队列并进行调度。

5:strand是从Write完成处理程序中调用的,并且不是async_write

我想知道我的上述说法是否正确。

1 个答案:

答案 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( );
        }
    } ));
}