并发async_write.有没有免等待的解决方案

concurrent async_write. is there a wait-free solution?

本文关键字:等待 解决方案 有没有 async write 并发      更新时间:2023-10-16
禁止

从不同的线程同时调用async_write()。它使用async_write_some按块发送数据,并且这些块可以交错。因此,用户有责任注意不要同时调用async_write()

有没有比这个伪代码更好的解决方案?

void send(shared_ptr<char> p) {
  boost::mutex::scoped_lock lock(m_write_mutex);
  async_write(p, handler);
}

我不喜欢长时间阻止其他线程的想法(我的应用程序中有~50Mb的发送)。

也许这样的东西会起作用吗?

void handler(const boost::system::error_code& e) {
  if(!e) {
    bool empty = lockfree_pop_front(m_queue);
    if(!empty) {
      shared_ptr<char> p = lockfree_queue_get_first(m_queue);
      async_write(p, handler);
    }
  }
}
void send(shared_ptr<char> p) {
  bool q_was_empty = lockfree_queue_push_back(m_queue, p)
  if(q_was_empty)
    async_write(p, handler);
}

我更愿意找到一个现成的食谱食谱。处理无锁并不容易,可能会出现很多微妙的错误。

禁止async_write() 从不同的同时调用 线程

这种说法不太正确。应用程序可以自由地同时调用async_write,只要它们位于不同的socket对象上即可。

有没有比这更好的解决方案 伪代码?

void send(shared_ptr<char> p) {
  boost::mutex::scoped_lock lock(m_write_mutex);
  async_write(p, handler);
}

这可能不会实现您的预期,因为async_write会立即返回。如果希望在整个写入操作期间锁定互斥锁,则需要在调用完成处理程序之前将scoped_lock保持在作用域中。

对于这个问题有更好的解决方案,该库具有使用链概念的内置支持。它非常适合这种情况。

链被定义为严格 事件的顺序调用 处理程序(即无并发 调用)。使用绞线允许 在多线程中执行代码 无需显式的程序 锁定(例如使用互斥锁)。

在此处使用显式链将确保您的处理程序仅由调用io_service::run()的单个线程调用。在您的示例中,m_queue成员将受到链的保护,从而确保对传出消息队列的原子访问。将条目添加到队列后,如果大小为 1,则表示没有未完成的async_write操作正在进行中,应用程序可以启动一个通过链包装的操作。如果队列大小大于 1,则应用程序应等待async_write完成。在async_write完成处理程序中,从队列中弹出一个条目,并根据需要处理任何错误。如果队列不为空,则完成处理程序应从队列前面启动另一个async_write

这是一个更简洁的设计,可以在您的类中散布互斥体,因为它按预期使用内置的 Asio 构造。我写的另一个答案有一些实现此设计的代码。

我们通过在

套接字对象中保留一个单独的数据队列来解决这个问题。 当要写入的第一条数据"排队"时,我们开始async_write()。 在async_write的完成处理程序中,如果仍有数据要传输,我们将开始后续async_write操作。

相关文章: