2017-08-29 191 views
0

我正在编写一个程序,该程序将读取的数据转发给另一个对等设备。 我有一个方法,在每次读取套接字上的数据后被调用。此方法将数据发布到一个链中,以将其写回另一个对等体。发送大块数据时,应用程序发回的数据与收到的数据不一样,问题是数据不再有序。这只是在boost :: asio :: io_service中使用多个线程的情况。即使在使用strand时,async_writes的排序也不正确

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

回答

4

当使用链:

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

执行顺序是:

  1. thing的处理程序
  2. must_be_done_now_A
  3. must_be_done_now_C
  4. thing的处理程序完成
  5. 在此期间
  6. may_be_done_out_of_order_B
+0

1.我从来没有直接张贴处理程序io_service对象钻进io_service任何其他的东西,我总是用链 2.每async_write处理程序已被包装在一个链中 3.我试图用调度来替换该文章,但同样的问题。任何其他想法?为什么它在回复:: postBackendReply中订购(所以这里没有问题的订单),但不是在postReply?这里会发生什么? –

+0

@BenD如果你不包装你的处理程序,所有的订购都是运气。 –

+0

@BenD在你的函数'postReply'中,你实际上发布了一篇文章。订单已不再保证。 –

相关问题