用于多线程应用程序的数据结构(以及C中的跨平台实现)

时间:2012-09-03 13:54:24

标签: c multithreading data-structures cross-platform

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

  1. 线程池应该对数据块的文件类型进行分类
  2. 每个线程都从此(阻塞)数据结构中读取
  3. 另一个线程(不是线程池的一部分)从存储设备读取块并将它们提供给数据结构。
  4. 如果没有更多可用数据,则读取线程会通知(或中断)数据结构,以便池中的被阻塞线程可以退出并关闭。
  5. 你认为阻塞FIFO队列在这里适合/充足吗?另一个要求是数据结构可以作为开源使用,并且可以针对不同的操作系统(至少Windows / Linux)进行编译。

    APR Util library看起来很有希望,但Visual Studio的项目文件适用于此编译器套件的史前版本。

2 个答案:

答案 0 :(得分:1)

生产者 - 消费者FOFO阻塞队列似乎是合理的。 ALl多线程操作系统具有合适的信号量/互斥量/ condvars /用于制作P-C队列的任何内容,您可以在一个特定于操作系统的接口单元中定义。

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

在做这种事情时,我通常会创建一个大的“池队列”(另一个P-C队列),在app启动时填充malloced / calloced * SomeStruct。然后,线程只将* SomeStructs从池中传入读取线程,传递到线程池FIFO,进入处理线程,最后返回池队列。这种流程控制数据,防止内存失控并消除连续的malloc / free。

编辑:

是的,FOFO是一个FOOBAR。

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

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

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

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

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

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

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

答案 1 :(得分:1)

当然,阻塞队列非常适合生产者 - 消费者模式。如果您想要便携式设备,请尝试使用英特尔TBB,特别是tbb::concurrent_bounded_queue