生产者-消费者 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] 数组可以作为队列的基础,您无需检查索引是否已满或需要使用额外的信号量来计算 '空的空间':)
哦 - 关机 - 我可能不会打扰关闭线程。如果他们无事可做,他们可以坐在那里,什么也不做,直到应用程序关闭。如果您确实需要关闭处理线程,请在告诉接收线程将药丸推回的队列上发送一条“毒丸”消息(空指针是一个很好的药丸 - 它不需要释放)队列,然后清理并退出 - 在短时间内,所有处理线程都会得到药丸并自杀。