5

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

我有什么选择?

我想到了以下几点:

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

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

4

2 回答 2

2

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

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

然后仅在准备添加充满消息的双端队列时锁定顶级双端队列。写入线程将反过来仅锁定顶级双端队列以弹出一个充满要写入的消息的双端队列。

于 2012-11-16T22:14:18.107 回答
2

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

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

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

在接收者线程中:

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

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

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

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

于 2012-11-17T00:25:27.830 回答