在c++中,人们实际使用哪些无锁原语来进行无锁音频处理



任何做过一些低级音频编程的人都会被警告不要锁定音频线程。这是一篇关于这个主题的好文章。

但我不清楚如何在严格遵守这一规则并确保线程安全的同时,用c++制作一个多线程音频处理应用程序。假设你正在构建一些简单的东西,比如可视化工具。您需要将音频数据交给UI线程来处理它,并定期显示它。

我的第一次尝试是在两个缓冲区之间打乒乓球。buffer*_write_state是一个布尔类型,假定为原子类型且无锁。buffer*是一种缓冲区,它本身并不期望线程安全,并且有一些方法可以处理一个线程被调用的速率不足的情况(我不想在这里讨论这个问题的复杂性(。对于一个看起来通用的布尔类型,实现如下所示:

// Write thread.
if (buffer1_write_state) {
buffer1.write(data);
if (buffer2_write_state) {
buffer1_write_state = false;
}
} else {
buffer2.write(data);
if (buffer1_write_state) {
buffer2_write_state = false;
}
}
// Read thread.
if (buffer1_write_state) {
data = buffer2.read();
buffer2.clear();
buffer2_write_state = true;
} else if (buffer2_write_state) {
data = buffer1.read();
buffer1.clear();
buffer1_write_state = true;
}

我已经使用std::atomic_flag作为我的布尔类型实现了这一点,并且据我所知,它是线程安全的。标准保证std::atomic_flag是无锁的。让我困惑的是,要做到这一点,我需要std::atomic_flag的test((函数,它在c++20之前是不存在的。可用的、可变的test_and_set((和clear((函数不能完成这项工作。众所周知的替代方案std::atomic不保证被标准锁定。我听说大多数情况下都不是。

我读过一些帖子,提醒人们不要尝试使用无锁结构,我很乐意遵守这一提示,但如果基本工具不能保证是无锁的,专家们该如何构建这些东西呢?

我听说在大多数情况下它不是。

你听错了。

CCD_ 1是"所有"上的锁定自由;正常的";C++实现,例如用于ARM、x86、PowerPC等。如果atomic_flag的限制性API太差,请使用它。或者std::atomic<int>,也相当普遍地对具有无锁定任何内容的目标进行无锁定。

(唯一可能的例外是一台8位机器无法加载/存储/RMW一对字节。(


请注意,如果您的目标是ARM,您应该启用编译器选项,让它知道您不在乎ARM CPU太旧而无法支持原子操作。在这种情况下,编译器将不得不生成慢速代码,在情况下使用库函数调用它在ARMv4或其他平台上运行。参见std::atomic<bool>ARM(树莓派3(上的无锁定不一致

最新更新