人们实际使用哪些无锁原语在 C++ 中进行无锁音频处理?
What lock-free primitives do people actually use to do lock-free audio processing in c++?
任何做过一些低级音频编程的人都被警告要锁定音频线程。 Here's 关于这个主题的一篇不错的文章。
但我不太清楚如何在严格遵循此规则并确保线程安全的同时,真正着手用 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 as my boolean type and as far as I can tell with my thread sanitizer, it is thread safe. std::atomic_flag is guaranteed to be lock free by the standard. The point that confuses me is that to even do this, I need std::atomic_flag's test() function which doesn't exist prior to c++20. The available, mutating test_and_set() and clear() functions don't do the job. Well known alternative std::atomic 实现了这个,但标准不保证是无锁的。我听说大多数情况下都不是。
我读过一些帖子,警告人们不要自己尝试使用无锁结构,我很乐意遵守该提示,但如果基本工具,专家们如何构建这些东西不保证无锁?
I've heard that it most cases it isn't.
你听错了。
std::atomic<bool>
是 lock_free 在所有“正常”C++ 实现上,例如适用于 ARM、x86、PowerPC 等。如果 atomic_flag
的限制性 API 太糟糕,请使用它。或者 std::atomic<int>
,在具有 lock-free 任何东西的目标上也相当普遍 lock_free。
(唯一可能的例外是不能 load/store/RMW 一对字节的 8 位机器。)
请注意,如果您的目标是 ARM,则应启用编译器选项以让它知道您不关心太旧而无法支持原子操作的 ARM CPU。在这种情况下,编译器将不得不编写使用库函数调用的慢速代码 case 它在 ARMv4 或其他平台上运行。参见
任何做过一些低级音频编程的人都被警告要锁定音频线程。 Here's 关于这个主题的一篇不错的文章。
但我不太清楚如何在严格遵循此规则并确保线程安全的同时,真正着手用 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 as my boolean type and as far as I can tell with my thread sanitizer, it is thread safe. std::atomic_flag is guaranteed to be lock free by the standard. The point that confuses me is that to even do this, I need std::atomic_flag's test() function which doesn't exist prior to c++20. The available, mutating test_and_set() and clear() functions don't do the job. Well known alternative std::atomic 实现了这个,但标准不保证是无锁的。我听说大多数情况下都不是。
我读过一些帖子,警告人们不要自己尝试使用无锁结构,我很乐意遵守该提示,但如果基本工具,专家们如何构建这些东西不保证无锁?
I've heard that it most cases it isn't.
你听错了。
std::atomic<bool>
是 lock_free 在所有“正常”C++ 实现上,例如适用于 ARM、x86、PowerPC 等。如果 atomic_flag
的限制性 API 太糟糕,请使用它。或者 std::atomic<int>
,在具有 lock-free 任何东西的目标上也相当普遍 lock_free。
(唯一可能的例外是不能 load/store/RMW 一对字节的 8 位机器。)
请注意,如果您的目标是 ARM,则应启用编译器选项以让它知道您不关心太旧而无法支持原子操作的 ARM CPU。在这种情况下,编译器将不得不编写使用库函数调用的慢速代码 case 它在 ARMv4 或其他平台上运行。参见