我有一个后台功能,目前有类似的内容:
void SomeClass::someFunction()
{
if (!_mutex.tryLock())
{
// i want to know the mutex is locked, and then exit the function
return;
}
else
{
_mutex.unlock();
}
QMutexLocker locker(_mutext);
// do some stuff that **could** throw an exception
}
我的困境涉及_mutex.unlock()
和QMutextLocker
声明。
如果_mutex
被锁定,那么我想知道它。如果不是,那么我想锁定它。问题是我想使用QMutexLocker
锁定_mutex
以获取大部分功能。该函数可能会抛出异常,因此手动解锁_mutex
可能很困难并且容易出错。
上述解决方案有效,但我担心的是,在_mutex.unlock()
和QMutexLocker
减速之间的某个时间可能出现其他内容并锁定互斥锁。
有没有人有更好的方法可以做到这一点?
谢谢。
答案 0 :(得分:6)
QMutexLocker显然不能满足您的需求,但您可以轻松编写自己的RAII包装器:
class MutexTryLocker {
QMutex &m_;
bool locked_;
public:
MutexTryLocker(QMutex &m) : m_(m), locked_(m.tryLock()) {}
~MutexTryLocker() { if (locked_) m_.unlock(); }
bool isLocked() const { return locked_; }
}
并像这样使用它:
void SomeClass::someFunction() {
MutexTryLocked locker(_mutex);
if (!locker.isLocked()) {
// we didn't get the lock, so return
return;
}
// do some stuff that **could** throw an exception
}
请注意,这个储物柜只是示例代码:生产版本应该是明确不可复制的。
历史记录:JBL的评论提到了一个不再在问题中处理句子的段落。我会把它解释为:
......还有其他东西可以锁定互斥锁
如果可能,将发生。如果不太可能,只有在部署/扩展/出售给客户后才会发生。
答案 1 :(得分:0)
我遇到了类似的情况,最终使用了等效的标准组件而不是Qt组件,因为它们的lock_guard能够处理已经锁定的互斥体。如果这是某人的选择,则可以通过以下方式做到这一点:
#include <mutex>
std::mutex _mutex;
void SomeClass::someFunction()
{
if (!_mutex.try_lock())
{
// i want to know the mutex is locked, and then exit the function
return;
}
// The lock_guard overtakes the already locked mutex
const std::lock_guard<std::mutex> locker(_mutex, std::adopt_lock);
// do some stuff that **could** throw an exception
}
答案 2 :(得分:-1)
我想出了另一种不需要编写自己的类的解决方案:
navigationBar