c++ - 如何断言 std::mutex 是否被锁定?

标签 c++ linux gcc c++11

使用 GCC 4.8.2(在 Linux/Debian/Sid 64 位上)-或 GCC 4.9(如果可用)-在 C++11 中-我有一些互斥体

std::mutex gmtx;

实际上,它是某个类 Foo 中的 static 成员,其中包含 alphabeta方法如下。

它被锁定在 alpha 之类的

void alpha(void) {
   std::lock_guard<std::mutex> g(gmtx);
   beta(void);
   // some other work
}

我想检查 beta 确实 gmtx 已锁定:

void beta(void) {
   assert (gmtx.is_locked());
   // some real work
}

(注意 is_locked 只在 assert 内部被调用...它可能非常低效甚至有时不准确)

当然,我还有其他调用beta的函数,例如

void gamma(void) {
   std::lock_guard<std::mutex> g(gmtx);
   beta();
   // some other work
}

但是is_locked 不存在....我应该如何定义它? (实际上我想确保互斥锁已被某些 [indirect] 调用者锁定在同一个线程中......)

(我想用 assert 测试的原因是 beta 可以在别处调用)

我不能使用 try_lock(除非使用递归互斥锁),因为在常见的情况下它会锁定一个已经锁定的互斥锁...(被调用者锁定在同一个线程中)而这不是只有未定义的行为,但完全阻止。

我想避免递归互斥锁(比普通互斥锁更昂贵),除非我真的必须这样做。


注意:真正的程序有点复杂。实际上,所有方法都在一个类中,该类在“项目”上保持命名双向关系。所以我在那个类里面有一个从项目到名称的映射和另一个从名称到项目的映射。 beta 将是添加真正命名的内部方法,而 alphagamma 将是通过名称查找或添加项目的方法, 或其项目的名称。

PS:真正的程序还没有发布,但应该成为MELT的一部分- 它的 future monitor ;您可以从 here 下载它(alpha 阶段,非常有问题) (临时位置)

最佳答案

严格来说,问题是关于直接检查 std::mutex 的锁定性。但是,如果允许将其封装在新类中,则很容易做到:

class mutex :
    public std::mutex
{
public:
#ifndef NDEBUG
    void lock()
    {
        std::mutex::lock();
        m_holder = std::this_thread::get_id(); 
    }
#endif // #ifndef NDEBUG

#ifndef NDEBUG
    void unlock()
    {
        m_holder = std::thread::id();
        std::mutex::unlock();
    }
#endif // #ifndef NDEBUG

#ifndef NDEBUG
    /**
    * @return true iff the mutex is locked by the caller of this method. */
    bool locked_by_caller() const
    {
        return m_holder == std::this_thread::get_id();
    }
#endif // #ifndef NDEBUG

private:
#ifndef NDEBUG
    std::atomic<std::thread::id> m_holder;
#endif // #ifndef NDEBUG
};

注意以下几点:

  1. 在 Release模式下,这对 std::mutex 的开销为零,但构造/销毁可能除外(这对于互斥对象来说不是问题)。
  2. m_holder 成员只能在获取互斥体和释放它之间访问。因此,互斥体本身充当m_holder 的互斥体。由于对 std::thread::id 类型的假设非常弱,locked_by_caller 将正常工作。
  3. 其他 STL 组件,例如 std::lock_guard 是模板,因此它们与这个新类配合得很好。

关于c++ - 如何断言 std::mutex 是否被锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21892934/

相关文章:

c++ - 检测 fork() 中的子进程创建

python - Cython 中的这个声明是什么? cdef PyObject ** worker 。它是指向指针的指针吗?

c++ - 在两个线程之间传递数据时的时间不一致

linux - 从期望脚本运行本地命令

linux - 两台linux机器之间使用wlan进行数据通信

c++ - 什么时候为 gcc 使用 -O2 标志?

gcc - 在 GCC 中为代码指定节名称

c++ - OpenCV 不会加载图像

c - ptrace(),如何停止在子进程中被跟踪?

c++ - 使用 CMake 和 C++ 处理共享库依赖