如何实现独立于平台的异步文件写入



我正在创建一个程序,该程序将从远程机器接收消息,并需要将消息写入磁盘上的文件。我发现的困难在于,这个程序的目的是测试接收消息的库的性能,因此,我需要确保将消息写入磁盘不会影响库的性能。库通过回调函数将消息传递给程序。另一个困难是解决方案必须独立于平台。

我有什么选择?

我想到了以下内容:

  • 使用boost:asio写入文件,但异步写入文件似乎在该库的Windows特定部分,因此无法使用
  • 使用boost::interprocess创建消息队列,但本文档指出有3种方法可以发送消息,如果消息队列已满,所有方法都需要程序阻止(隐式或不阻止),我不能冒险
  • 创建一个std::deque<MESSAGES>,从回调函数推送到deque,并在写入文件时弹出消息(在单独的线程上),但STL容器不能保证线程安全。我可以锁定推送和弹出deque,但我们谈论的是连续消息之间的47微秒,所以我想完全避免锁定

有人对可能的解决方案有更多想法吗?

STL容器可能不是线程安全的,但我从未遇到过不能在不同时间在不同线程上使用的容器。将所有权传递给另一个线程似乎是安全的。

我已经使用了以下几次,所以我知道它有效:

  • 创建一个指向std::向量的指针
  • 创建一个互斥锁来保护向量指针
  • 使用new[]创建一个std::向量,然后为它保留一个大的大小()

在接收器线程中:

  • 每当向队列中添加项目时,都会锁定互斥对象。这应该是一个短锁
  • 添加队列项目
  • 松开锁
  • 如果你觉得这是一个条件变量的信号。我有时不会:这取决于设计。如果音量很高,并且接收端没有暂停,只需跳过条件并轮询即可

在使用者线程(磁盘写入程序)上:

  • 通过轮询或等待条件变量来查找要做的工作:
  • 锁定队列互斥
  • 看看队列长度
  • 如果队列中有工作,则将指针分配给使用者线程中的变量
  • 使用new[]和reserve()创建一个新的队列向量,并将其分配给队列指针
  • 解锁互斥锁
  • 离开并将您的项目写入磁盘
  • 删除[]已用完的队列向量

现在,根据您的问题,您可能最终需要一种方法来阻止。例如,在我的一个程序中,如果队列长度达到100000个项目,生产线程就会开始睡1秒,并抱怨很多。这是不应该发生的事情之一,但确实发生了,所以你应该考虑一下。在没有任何限制的情况下,它只会使用机器上的所有内存,然后异常崩溃,被OOM杀死,或者在交换风暴中停止。

boost::thread是独立于平台的,因此您应该能够利用它创建一个线程来执行阻塞写入。为了避免每次将消息放入主线程时都需要锁定容器,您可以通过创建嵌套容器来修改双缓冲技术,例如:

std::deque<std::deque<MESSAGES> >

然后,只有当准备添加一个装满消息的deque时,才锁定顶级deque。写入线程将只锁定顶级deque,以弹出一个充满要写入的消息的deque。

最新更新