boost :: asio :: strand :: dispatch(handle)或直接调用句柄?

时间:2016-07-01 03:22:21

标签: c++ boost boost-asio

我是boost :: asio的新手。提升doc说:

  

strand对象保证通过strand发布或分派的处理程序不会同时执行。如果可以满足保证,则可以在该函数内执行处理程序。如果从通过同一链发布或分派的处理程序中调用此函数,则将立即执行新处理程序。

所以我想知道新处理程序何时立即执行,为什么不直接调用它而不是使用dispatch?

1 个答案:

答案 0 :(得分:4)

如果调用者总是在strand中运行,那么可以直接调用处理程序。否则,如果调用者并不总是在strand中运行,那么可以使用strand.dispatch()来满足并发要求,同时可能优化某些调用链。

例如,考虑应用程序协议要求在周期性和响应每个心跳请求时发送心跳的情况。可以设计异步调用链,以便有两个离散的调用链:

  • keepalive类负责定期发送心跳的调用链。它将设置一个计时器到期,并在到期时设置一个新的到期时间并发送心跳:

         .---------------------------.
         V                           |
    keepalive::start_timer()         |
    {                                |
      timer_.expires_from_now(...);  |
      timer_.async_wait(             |
        [this](...)                  |
        {                            |
          this->start_timer();  -----'
          io.send_headerbeat();
        });
    }
    
    keepalive.start_timer();
    
  • io类管理套接字,使用私有链来序列化对套接字的访问。 io类将从套接字读取并处理读取数据。

        .-------------------------------------.
        V                                     |
    io::read_data()                           |
    {                                         |
      async_read(socket_, buffer_,            |
        strand_.wrap([this](...)              |
        {                                     |
          auto message = parse(buffer_);      |
          this->read_data();  ----------------'
          if (is_heartbeat_request(message))
          {
            this->send_heartbeat();
          }
        }));
    }
    
    io::start()
    {
      strand_.post([this]{ this->read_data(); });
    }
    

keepalive的调用链中,io::send_heartbeat()io的私有链外部调用keepalive无法访问的io。另一方面,在io::send_heartbeat()的调用链中,io::send_heartbeat()从链内调用。如果io调度将在套接字上启动写操作的处理程序,那么它将对两个异步调用链正常且透明地工作。此外,在io::send_heartbeat() { strand_.dispatch( [this]() { async_write(this->socket_, ..., this->strand_.wrap(...)); }); } 调用链中调用时,处理程序立即执行,避免了发布和与链同步的开销。

true

strand::dispatch()将立即执行当前线程中的处理程序:

  • strand::running_in_this_thread()返回strand::running_in_this_thread()
  • false返回io_service,调用者正在运行strand::dispatch(),并且可以满足strand指定的处理程序调用顺序

没有公共API来确定第二种情况的所有条件。因此,无法确定直接调用处理程序是否安全,而必须改为使用var dummyArray = []; for (var i = 0; i < res.data.length; i++) { if(dummyArray.indexOf(res.data[i]._id === -1) { $scope.collections.push(res.data[i]); dummyArray.push(res.data[i]._id); } else { break; } }