详细介绍:
在复杂函数和声明中,在异常处理中,锁定和解锁一个QMutext对象不但很容易犯错,还很难调试。
下面的QMutexLocker使用场景,会告诉你如何恰当地定义mutex。
函数中,哪里需要被锁定,就在哪里创建QMutexLocker。一旦QMutexLocker对象被创建,互斥体就被锁定了。
unlock()和relock()可用来解锁互斥体。即使互斥体已被锁定,当QMutexLocker对象被析构摧毁后,互斥体会自动解锁。
例子:在函数开始处,锁定互斥体对象,在每个函数出口处解锁互斥体。
int complexFunction(int flag)
{
mutex.lock();
int retVal = 0;
switch (flag) {
case 0:
case 1:
retVal = moreComplexFunction(flag);
break;
case 2:
{
int status = anotherFunction();
if (status < 0) {
mutex.unlock();
return -2;
}
retVal = status + flag;
}
break;
default:
if (flag > 10) {
mutex.unlock();
return -1;
}
break;
}
mutex.unlock();
return retVal;
}
开发这样的函数会更麻烦,也更容易出错。使用QMutexLocker不仅极大地简化了编码,代码易读性也更高了:
int complexFunction(int flag)
{
QMutexLocker locker(&mutex);
int retVal = 0;
switch (flag) {
case 0:
case 1:
return moreComplexFunction(flag);
case 2:
{
int status = anotherFunction();
if (status < 0)
return -2;
retVal = status + flag;
}
break;
default:
if (flag > 10)
return -1;
break;
}
return retVal;
}
QMutexLocker对象是一个自动变量,函数返回时,对象自动被摧毁析构,互斥体随之自动解锁。
同样的道理也适用于会抛出异常的编码。
若函数已锁定互斥体,但没有捕获到函数内发生的异常。
那么只有当异常被传递到调用它的函数的栈时,互斥体才能被解锁.
QMutexLocker也提供了QMutexLocker运行过程中可返回互斥体的成员函数。
像QWaitCondition::wait(),这样需要访问互斥体的编码,该成员函数非常有用。
例子:
class SignalWaiter
{
private:
QMutexLocker locker;
public:
SignalWaiter(QMutex *mutex)
: locker(mutex)
{
}
void waitForSignal()
{
...
while (!signalled)
waitCondition.wait(locker.mutex());
...
}
};