0

我有一个音频 dsp 应用程序,它使用线程池以比实时快得多的速度产生输出。这旨在用于游戏,并且音频必须以相当低的延迟进行流式传输。每个完成的缓冲区都在主混音器线程中结束,我需要将其传递给应用程序程序员。我想我可能在主类中有一个 read_samples 方法,它需要一个缓冲区指针和一些要读取的样本,并返回实际读取的样本数。

我正在研究一个无锁 fifo,即来自 boost.lockfree 的单个生产者/单个消费者队列。我目前的设计目标如下:

  1. 数据从 fifo 快速推入和推出非常重要,因此我们希望尽可能少的阻塞操作。大多数时候,应用程序程序员可能会在中断级别优先级线程内调用主类的 read_samples 方法,因为许多音频 I/O 子系统以这种方式接收数据(例如通过回调)。因此,我们来到第 2 点和第 3 点。

  2. 如果调用了 read_samples 并且 fifo 中没有足够的样本来交付请求的数量,我们可能应该获取我们所拥有的(如果有的话)然后立即返回而不阻塞。如果我们锁定并等待,我们可能会影响中断级别线程回调可能负责的许多其他音频播放。

  3. 如果生产者尝试写入一个完整的缓冲区,我们希望等到所有样本都被写入。我们希望让用户在等待写入时读取,以便他们可以为我们清理缓冲区中的空间。生产者等待是没有问题的,因此该部分不需要无锁。通过设置与我们的延迟预期大致对应的环形缓冲区大小,我们可以确保生产者为我们提供足够的数据以避免播放停止,但仅此而已。

第一点和第二点实际上是微不足道的,前提是我的设计决定何时以及何时不阻塞似乎是合理的。这是第三点给我带来了一些麻烦。有没有一种有效的方法来锁定直到缓冲区不再满,并且只有在我们可以写更多时才唤醒?我可以很容易地检测到缓冲区的大小,谢天谢地,这是一个原子操作。但是如何适当地锁定和解锁让我感到困惑,特别是因为我们确实希望能够在需要关闭时提前中断锁定。我用什么来做这个?条件变量?如果是这样,如果有人能提供一些伪代码,我将非常感激。我了解如何使用障碍,但还没有过多地研究条件变量,并且不确定我是否理解它们。特别是因为他们显然可以在没有满足条件的情况下醒来,这似乎很奇怪。任何建议将不胜感激。

4

1 回答 1

0

当生产者生产了太多材料时,获得阻塞行为的正确方法是使用条件变量。生产者在达到其限制时调用 wait ,然后消费者在消耗了一些数据后立即调用 notify_all 。然后生产者醒来并产生更多,等等。

于 2013-04-07T17:27:08.957 回答