简体   繁体   中英

Am I paranoid while using boost:asio?

I am write an app using boost:asio.

I have a single io_serice::run() thread, and many worker threads. All the worker threads may send msg at any time.

Here is how I implement the send_msg() .

// Note: send_msg() could be called from any thread.
// 'msg' must be 'malloc'ed, and its owner ship will be transfered  to '_send_q'
//
//  NetLibConnection has base classes of tcp::socket and  boost::enable_shared_from_this
void NetLibConnection::send_msg(PlainNetLibMsg*  msg)
{
    AutoLocker __dummy(this->_lock_4_send_q);    // _lock_4_send_q is a 'mutex'

    bool write_in_progress = ! this->_send_q.empty(); // _send_q is std::deque<PlainNetLibMsg* >, 
                                           // the 'send_q' mechansim is learned from  boost_asio_example/cpp03/chat  
    this->_send_q.push_back(msg);
    if (write_in_progress)
    {
        return;
    }

    this->get_io_service().post(      // queue the 'send operation' to a singlton io_serivce::run() thread

        boost::bind(&NetLibConnection::async_send_front_of_q
                , boost::dynamic_pointer_cast<NetLibConnection>(shared_from_this())
        ) 
    );
      
}

void NetLibConnection::async_send_front_of_q()
{
    boost::asio::async_write(*this 
        , boost::asio::buffer( this->_send_q.front() , _send_q.front()->header.DataSize + sizeof(NetLibChunkHeader) )
        , this->_strand.wrap(  // this great post   https://stackoverflow.com/questions/12794107/why-do-i-need-strand-per-connection-when-using-boostasio/
                              // convinced me that I should use strand along with  Connection
            boost::bind( &NetLibConnection::handle_send
                        , boost::dynamic_pointer_cast<NetLibConnection>(shared_from_this()) 
                        , boost::asio::placeholders::error
            )
        )
    );
}

The code works fine. But I am not satisfied with its verbosity. I feel the senq_q acts as the same role of strand . Since

  1. all real async_write call happen in a single io_service::run() thread
  2. all real async_write are queued one-by-one via the send_q

Do I still need the strand ?

Yes, indeed. The documentation details this here:

Threads And Boost Asio

By only calling io_service::run() from a single thread, the user's code can avoid the development complexity associated with synchronisation. For example, a library user can implement scalable servers that are single-threaded (from the user's point of view).

Thinking a bit more broadly, your scenario is the simplest form of having a single logical strand. There are other ways in which you can maintain logical strands (by chaining handlers), see this most excellent answer on the subject: Why do I need strand per connection when using boost::asio?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM