如何将 std::condition_variable 与我自己的互斥包装器一起使用

How to use std::condition_variable with my own mutex wrapper

我想演示/记录一些 std::mutex 行为。我想记录对 lock()unlock() 的每次调用(无论它们是成功还是必须阻止)。最初,由于那些方法不是 virtual,我尝试用以下方式包装标准 std::mutex,而不是使用继承:

struct mutex_wrapper {
    std::mutex mut = std::mutex();

    void lock() {
        std::cout << "LOCKING MUTEX\n";
        mut.lock();
    }

    void unlock() {
        std::cout << "UNLOCKING MUTEX\n";
        mut.unlock();
    }
};

忽略在多个线程中调用 std::cout << 时可能产生错误输出的事实。

然后我想检查一个简单的 std::condition_variable 示例的输出,例如:

int main() {
    auto ready = false;
    auto mutex = mutex_wrapper();
    auto cvar = std::condition_variable();

    auto t = std::thread([&mutex, &cvar, &ready] {
        std::unique_lock lock(mutex);
        cvar.wait(lock, [&ready] { return ready; });
        std::cout << "woke up\n";
    });

    std::this_thread::sleep_for(std::chrono::seconds(2));
    {
        std::lock_guard lock(mutex);
        ready = true;
    }
    std::cout << "notifying\n";
    cvar.notify_one();

    t.join();
}

问题是它无法编译,因为显然,wait() 要求相应的 std::unique_lock 使用常规 std::mutex 实例化,而我试图将其与我的一起使用拥有 mutex_wrapper.

有什么方法可以记录标准互斥体锁定和解锁的内部使用情况吗?或者有没有办法让 std::condition_variable 使用包装器?

std::condition_variable 仅适用于 std::unique_lock<std::mutex>——因此您可能希望使用 std::condition_variable_any。这是 std::condition_variable 的概括,可以与任何 BasicLockable 类型一起使用,例如互斥包装器。

请注意,与直接使用 std::condition_variable/std::mutex 相比,这可能有点悲观,因为通常这些在实现中紧密耦合以获得更好的性能。但既然你在这里登录,我怀疑这总体上不会是什么大问题。

另一种方法是编写您自己的自定义 condition_variable 包装器,该包装器直接根据包装的 mutex 类型和基础 std::condition_variable 进行操作 - 并提取 std::mutex直接加锁的时候。