我在使用
std::condition_variable
和自定义旋转互斥体实现时遇到困难。似乎 std::condition_variable
期望 std::mutex
与其锁相关联,从而在尝试使用不同的互斥锁实现时导致编译错误。
这是我的代码的简化版本,其中发生编译错误:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
class SpinMutex {
public:
void lock() {
// Implement spin lock logic here
}
void unlock() {
// Implement spin unlock logic here
}
private:
// Implement atomic flag or other spin lock mechanism here
};
SpinMutex mutex;
std::condition_variable cv;
bool ready = false;
void worker_thread() {
// Do some work...
std::this_thread::sleep_for(std::chrono::seconds(1));
// Attempting to lock a SpinMutex with std::lock_guard
// This line will throw a compilation error
std::unique_lock<SpinMutex> lock(mutex);
ready = true;
cv.notify_one();
}
int main() {
std::thread worker(worker_thread);
{
std::unique_lock<SpinMutex> lock(mutex);
cv.wait(lock, [] { return ready; });
}
worker.join();
return 0;
}
如图所示,将
std::unique_lock
与 SpinMutex
一起使用会引发编译错误。看起来 std::condition_variable
与 std::mutex 紧密耦合,使其与自旋互斥体等自定义互斥体实现不兼容。
我想我可以使用
std::condition_variable_any
,但我的问题是为什么标准决定这样做?是因为遗留目的还是因为他们对std::mutex
实施了特殊优化。换句话说,对于非天才开发人员来说,例如如上所述,我可以保证
SpinMutex
将优于我自己在一般中的实现吗? VS 实现捕获
std::mutex
是的,正确。
但我的问题是为什么标准决定这样做?
C++ 中同步 API 的目的是提供操作系统同步 API 的可移植包装器。 C++ API 的设计深受 Linux pthreads API 的影响。
因此
std::condition_variable_any
和
std::mutex
旨在成为底层操作系统 API 周围尽可能薄的包装器。就 pthread 而言,std::condition_variable
映射到 std::mutex
。并且 pthread_mutex_t
映射到 std::condition_variable
。还有一个pthread_cond_t
等待着一个
pthread_cond_t
。但当时意识到:
除了 pthread_mutex_t
std::mutex
std::mutex
的设计是为了满足那些想要等待通用互斥量概念的人的需求,同时又不让那些不需要这种通用性的人为该功能付费。
这是一篇早期论文,其中包含设计原理: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html#conditionstd::condition_variable_any
最终更名为
cond_var
。而本文所说的 condition_variable
最终被重命名为 gen_cond_var
。还值得注意的是:本文详细介绍了实施的难度condition_variable_any
。然而本文的实现中仍然存在一个错误。这比作者当时意识到的还要困难。然而,据我所知,从 C++11 开始,
gen_cond_var
的所有主要实现都没有错误。