2

我正在寻找以下场景的数据结构:

  1. 线程池应该对数据块的文件类型进行分类
  2. 每个线程都从这个(阻塞的)数据结构中读取
  3. 另一个线程(不是线程池的一部分)从存储设备中读取块并将它们馈送到数据结构中。
  4. 如果没有更多数据可用,读取线程会通知(或中断)数据结构,以便池中的阻塞线程可以退出并关闭。

您认为阻塞 FIFO 队列在这里合适/足够吗?另一个要求是数据结构可以作为开源获得,并且可以针对不同的操作系统(至少是 Windows/Linux)进行编译。

乍一看,APR Util 库看起来很有希望,但 Visual Studio 的项目文件是为这个编译器套件的史前版本而设计的

4

2 回答 2

1

生产者-消费者 FOFO 阻塞队列似乎是合理的。所有多线程操作系统都有合适的信号量/互斥量/condvars/任何东西来使 PC 排队,您​​可以在一个特定于操作系统的接口单元中定义它们。

我将使用的“数据结构”是 *SomeStruct 的队列,它可以包含数据块和处理该块所需的任何其他元数据。

在做这类事情时,我通常会创建一个大的“池队列”(另一个 PC 队列),在应用程序启动时填充了 malloced/calloced *SomeStruct。然后线程将只是将池中的 *SomeStructs 循环到读取线程,到线程池 FIFO,再到处理线程,最后返回到池队列。此流程控制数据,防止内存失控并消除连续的 malloc/free。

编辑:

是的,FOFO 是一个 FOOBAR。

我的设计使用两个 FIFO、线程安全、阻塞队列:

a) 池队列,在启动时填充固定数量的 malloced/calloced *SomeStructs。

b) 处理线程等待的处理队列。

读取线程从池队列中取出 *SomeStructs,加载它们,将它们排队到处理线程获取它们的处理队列,处理它们,然后在完成后将它们重新排队到池队列。

这意味着 SomeStructs 的数量仅限于启动时创建的数量,因此您无需在应用程序运行时再进行 malloc/calloc 或 free 操作。此外,如果读取线程试图“领先于”处理线程,则池队列将清空并且读取线程将阻塞它,直到处理线程返回一些“已使用”*SomeStructs 到池以供重用 -然后阅读线程将再次运行。

另一个优点是您不需要复杂的有界队列。由于 *SomeStruct 实例的总数仅限于启动时创建的数量,因此队列只需足够大以容纳该数量 - 它们永远不必再容纳。因此,一个简单的固定大小 *SomeStruct[CtotalInstances] 数组可以作为队列的基础,您无需检查索引是否已满或需要使用额外的信号量来计算 '空的空间':)

哦 - 关机 - 我可能不会打扰关闭线程。如果他们无事可做,他们可以坐在那里,什么也不做,直到应用程序关闭。如果您确实需要关闭处理线程,请在告诉接收线程将药丸推回的队列上发送一条“毒丸”消息(空指针是一个很好的药丸 - 它不需要释放)队列,然后清理并退出 - 在短时间内,所有处理线程都会得到药丸并自杀。

于 2012-09-03T15:21:26.370 回答
1

当然,阻塞队列非常适合生产者-消费者模式。如果您想要一些便携的东西,请尝试 Intel TBB,特别是tbb::concurrent_bounded_queue

于 2012-09-03T18:19:57.747 回答