简体   繁体   English

我什么时候必须使用boost :: asio:strand

[英]When do I have to use boost::asio:strand

Reading the document of boost::asio, it is still not clear when I need to use asio::strand. 阅读boost :: asio的文档,尚不清楚何时需要使用asio :: strand。 Suppose that I have one thread using io_service is it then safe to write on a socket as follows ? 假设我有一个使用io_service的线程,那么可以安全地在套接字上进行如下编写吗?

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;
    }
  }
}

Where multiple threads calls Connection::write(..) or do I have to use asio::strand ? 在多个线程调用Connection :: write(..)的地方,还是我必须使用asio :: strand?

Short answer: no, you don't have to use a strand in this case. 简短的回答:不,在这种情况下,您不必使用strand

Broadly simplificated, an io_service contains a list of function objects (handlers). 广义上讲, io_service包含功能对象(处理程序)的列表。 Handlers are put into the list when post() is called on the service. 在服务上调用post()时,将处理程序放入列表中。 eg whenever an asynchronous operation completes, the handler and its arguments are put into the list. 例如,每当异步操作完成时,将处理程序及其参数放入列表中。 io_service::run() executes one handler after another. io_service::run()执行一个处理程序。 So if there is only one thread calling run() like in your case, there are no synchronisation problems and no strand s are needed. 因此,如果像您的情况那样只有一个线程调用run() ,则不会出现同步问题,也不需要strand
Only if multiple threads call run() on the same io_service , multiple handlers will be executed at the same time, in N threads up to N concurrent handlers. 仅当多个线程在同一io_service上调用run()时,才会在N个线程(最多N个并发处理程序)中同时执行多个处理程序。 If that is a problem, eg if there might be two handlers in the queue at the same time that access the same object, you need the strand . 如果这是一个问题,例如,如果队列中可能同时有两个处理程序访问同一对象,则需要使用strand
You can see the strand as a kind of lock for a group of handlers. 您可以将strand视为一组处理程序的一种锁。 If a thread executes a handler associated to a strand , that strand gets locked, and it gets released after the handler is done. 如果线程执行与strand相关的处理程序,则该strand将被锁定,并在处理程序完成后释放。 Any other thread can execute only handlers that are not associated to a locked strand . 任何其他线程只能执行未与锁定strand关联的处理程序。

Caution: this explanation may be over-simplified and technically not accurate, but it gives a basic concept of what happens in the io_service and of the strand s. 注意:这个解释可能是过于简化和技术上不准确的,但它给在发生什么的一个基本概念io_service和的strand秒。

Calling io_service::run() from only one thread will cause all event handlers to execute within the thread, regardless of how many threads are invoking Connection::write(...) . 仅从一个线程调用io_service::run()将使所有事件处理程序在该线程中执行,而不管有多少线程正在调用Connection::write(...) Therefore, with no possible concurrent execution of handlers, it is safe. 因此,在没有可能并发执行处理程序的情况下,这是安全的。 The documentation refers to this as an implicit strand . 文档将其称为隐式链

On the other hand, if multiple threads are invoking io_service::run() , then a strand would become necessary. 另一方面,如果多个线程正在调用io_service::run() ,那么将需要一个子线程。 This answer covers strands in much more detail. 这个答案涵盖了更多的细节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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