如何实现平台无关的异步写入文件?

ajc*_*ana 5 c++ multithreading thread-safety boost-asio boost-interprocess

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

我有什么选择?

我想到了以下几点:

  • 使用boost:asio写入文件,但似乎(见文档),以文件异步写入是在该库的Windows特定的部分-所以这不能使用.
  • 使用boost::interprocess创建一个消息队列,但这个文件表明,有3种方法,其中的信息可以发送,并且所有的方法将需要程序来阻止(隐含与否)如果消息队列已满,我不能冒险.
  • 创建一个std::deque<MESSAGES>从回调函数推送到deque,并在写入文件时(在单独的线程上)弹出消息,但不保证 STL容器是线程安全的.我可以锁定推进,然后弹出deque但我们正在谈论连续消息之间的47微秒,所以我想完全避免锁定.

有没有人对可能的解决方案有任何想法?

Zan*_*ynx 2

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

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

  • 创建一个指向 std::vector 的指针。
  • 创建互斥锁来保护向量指针。
  • 使用 new[] 创建一个 std::vector ,然后为其保留一个大尺寸。

在接收者线程中:

  • 每当将项目添加到队列时就锁定互斥体。这应该是一个短锁。
  • 添加队列项目。
  • 释放锁。
  • 如果您觉得它发出了条件变量的信号。我有时不这样做:这取决于设计。如果音量非常高并且接收端没有暂停,则跳过该条件并进行轮询。

在消费者线程(磁盘写入器)上:

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

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