即使使用strand,async_writes的顺序也不正确

Ben*_*n D 0 c++ sockets multithreading boost boost-asio

我正在编写一个程序,该程序将读取的数据转发给另一个对等方。我有一个方法,每次在套接字上读取数据后都会被调用。此方法将数据分条发送,以将其写回到另一个对等方。当发送大量数据时,应用程序发送回的数据与接收到的数据不同,问题在于不再对数据进行排序。只有在boost :: asio :: io_service中使用多个线程时,才会出现这种情况。

在套接字上读取某些数据时,将调用handleGatewayReply。此时(1),在将数据写入文件之后,我可以看到数据仍然是有序的。此后,将调用postBackendReply,并且数据仍然有序(2)。但是在SessionConnection :: postReply中,如果我将数据刷新到文件(3),则可以看到不再对数据进行排序。我现在看不到为什么订单丢失了,我试图在handleGatewayReply和postBackendReply中使用一个代码段(如代码所示),但是行为仍然相同。

抱歉,我无法提交一个最小,完整和可验证的示例,因为该错误太难发现,需要多线程转发大量数据。

  void Reply::handleGatewayReply(std::stringstream* stream)
  {
    // Flush data to file (1)
    m_strand.post(std::bind([=]() {  
        postBackendReply(*stream);
      delete stream;
    }
    }));

  }

void Reply::postBackendReply(const std::stringstream& stream)
  {
    auto buffer = std::make_shared<Buffer>();
    buffer->m_buffers.push_back(stream.str());
    // Flush data to file (2)
    auto connection = m_request->connection();
    if (connection) {
//    connection->postReply(buffer); // doesn't work either
          m_strand.post(std::bind(&SessionConnection::postReply, connection,buffer));
    }

  }


  void SessionConnection::postReply(BufferPtr buffer)
  {
      // Flush data to file (3)
      m_ioService.post(
        m_ostrand.wrap(
          std::bind(&SessionConnection::sendNext, 
                    shared_from_this(), buffer)));
    }
  }
Run Code Online (Sandbox Code Playgroud)

Ric*_*ges 5

使用绞线时:

  1. 切勿将任何处理程序直接发布到io_service,以确保不会丢失顺序并破坏并发保证。

  2. strand::wrap 每个异步处理程序。

  3. 在(包装的)处理程序中,如果需要强制执行命令,dispatch则将其置于链上。只有post到它,如果,如果在未来的某个时刻执行张贴的处理器仍然是有效的。

例:

thing.async_op(mystrand.wrap([self = shared_from_this()](auto&& error){
    self->mystrand.dispatch(&must_be_done_now_A);
    self->mystrand.post(&may_be_done_out_of_order_B);
    self->mystrand.dispatch(&must_be_done_now_C);
});
Run Code Online (Sandbox Code Playgroud)

执行顺序为:

  1. thing的处理程序
  2. must_be_done_now_A
  3. must_be_done_now_C
  4. thing的处理程序完成
  5. 该钻进了任何其他的东西,io_service在此期间
  6. may_be_done_out_of_order_B