Using QMutex::tryLock and QMutexLocker

c++, concurrency, mutex, qt

Solution

QMutexLocker clearly doesn't do quite what you need here, but you can write your own RAII wrapper easily enough:

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_; }
}

and use it like so:

void SomeClass::someFunction() {
    MutexTryLocker locker(_mutex);

    if (!locker.isLocked()) {
        // we didn't get the lock, so return
        return;
    }

    // do some stuff that **could** throw an exception
}

Note this locker is just sample code: a production version should probably be explicitly noncopyable.

Historical note: JBL's comment referred to a paragraph addressing a sentence no longer in the question. I'll paraphrase it as:

... something else could come along and lock the mutex

If it's possible, it will happen. If it's unlikely, it will happen only after you deploy it/scale it up/sell it to a customer.

Problem

I have a background function that currently has something like follows: ``` 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 } ``` My dilemma concerns the `_mutex.unlock()` and `QMutextLocker` statement. If the `_mutex` is locked, then I want to know about it. If it's not, then I want lock it. The problem is that I want to use `QMutexLocker` to lock `_mutex` for the bulk of the function. It's possible that the function could throw an exception, so manually unlocking `_mutex` could be difficult and error prone. The above solution works but what concerns me is that sometime between the `_mutex.unlock()` and the deceleration of `QMutexLocker` something else could come along and lock the mutex. Does anyone have any suggestions of a better way to do this? Thank you.

Original source