0

我看到一个头文件如下:

#include <pthread.h>

#define lock(x) if(Lock _lock_=x){}else

class Mutex{
    public:
        Mutex(){
            pthread_mutex_init(&mutex_, 0);
        };

        ~Mutex(){
            pthread_mutex_destroy(&mutex_);
        };

        friend class Lock;

    private:
        pthread_mutex_t mutex_;

        void Lock(){
            pthread_mutex_lock(&mutex_);
        };

        void Unlock(){
            pthread_mutex_unlock(&mutex_);
        };
};

class Lock{
    public:
        Lock(Mutex& mutex):mutex_(mutex){mutex_.Lock();};
        ~Lock(){mutex_.Unlock();};

        operator bool() const {
            return false;
        }

    private:
        Mutex& mutex_;
};

它定义了一个lock(x)宏。下面是如何使用这个宏:

...
Mutex mtx;
lock(mtx) {
  // critical section
}
...

那么,这个锁宏是如何工作的呢?为什么?

4

2 回答 2

2

因此,预处理器将就地扩展宏(本质上是将其插入代码中)。所以你的例子变成:

...
Mutex mtx;
if(Lock _lock_=mtx){}else {
  // critical section
}
...

或者,使用更好的格式,

...
Mutex mtx;
if(Lock _lock_=mtx)
{
}
else
{
  // critical section
}
...

它通过Lock类的构造函数锁定 Mutex,并且由于's的实现,语句中的表达式if()总是计算结果为,因此执行该部分中的代码。falseLockoperator bool() constelse { }

我想我还会提到,我认为这是一种......比必要的方式更令人费解的方式来做到这一点。Lock在作用域的开头声明一个 new 并完全取消宏将是“同样容易”(并且可能更容易理解) 。例如,Qt 的 QMutexLocker就是这样使用的。

于 2013-10-09T17:29:13.087 回答
1

我们可以在这里做一些纸上的宏扩展:

你的宏=

#define lock(x) if(Lock _lock_=x){}else

以及它的用途:

Mutex mtx;
lock(mtx) {
  // critical section
}

宏替换后变为:

Mutex mtx;
if(Lock _lock_=mtx)
{
  // BLOCK 1
}
else
{
  // BLOCK 2
  // critical section
}

因此,_lock_正在从 复制分配mtx,它尝试通过调用来锁定互斥锁pthread_mutex_lock如果成功则返回0,如果互斥锁已被阻塞,则阻塞。

if块正在调用Lock::operator bool(),它总是返回false

运算符 bool() const { return false; }

因为这总是返回false,所以我标记的块永远不会被占用,而是调用BLOCK 1你的关键部分代码 ( )。BLOCK 2

于 2013-10-09T17:35:01.930 回答