views:

115

answers:

2

Hi,

I'm using a QReadWriteLock in my application to guard access to a resource object.

I'm using QReadLocks and QWriteLocks where I can, but sometimes I need a "long-lived" lock that crosses function boundaries. So sometimes I need to be able to query the state of the QReadWriteLock (or QMutex, same thing in this situation) because unlocking a mutex that is already unlocked is very bad.

For QMutex:

Unlocking a mutex that is not locked results in undefined behavior.

For QReadWriteLock:

Attempting to unlock a lock that is not locked is an error, and will result in program termination.

Being able to query the state of the mutex would also come in very handy for debug assertions to test that before starting some operation, I really do have that "long-lived" lock.

But all I really want is to be able to unlock a mutex if I have the lock, and not unlock it if I don't have it. That would make my day. IMO the unlock() function should already do this for me, but it doesn't.

Any way around this?

(and no, using Recursive mode does not help in this situation)

A: 

Use QMutex::locked() to determine the state of the mutex.

I don't believe there's an equivalent function in QReadWriteLock. That being said, you could use the tryLockForRead(), tryLockForWrite() functions (which return true or false depending) to ensure you managed to get the locks, and if so unlock them later.

Xorlev
The tryLock* approach (which I used before) fails if you're using Recursive mode, and I am. Also, QMutex::locked() is in the Qt3 support API (it's not in the official Qt4 one) which Nokia advises against using. I can't afford to use that. Also, I'm primarily using QReadWriteLock.
Lucas
You may need to just encapsulate the lock in your own class and keep a count of the number of times you locked and allow calls to MyLock.unlock() until num_locks reaches zero.
Xorlev
+1  A: 

Untested code, But this should be possible to do, if Qt Doc is correct (though it's a little short about when tryLock() returns true/false)

QMutex m;

bool queryMutexState(){
//static QMutex lock; if you call this frequent, you may need this "protector"
lock.lock();
bool b(m.tryLock());
if (b)
m.unlock();
//lock.unlock()
return b;
}

Try to lock, if it fails, return false (=mutex is aquired somewhere else), if it is not locked, tryLock() will lock it, so unlock it again and return true (=mutex is availiable)

Note: Another option would be a custom class with member QMutex and bool to indicate lock state. This may work better for you, as the mutex does not need to be locked and unlocked to get the state.

I suggest you go for method #2

penguinpower
While your first suggestion on using tryLock fails when the mutex is in Recursive mode (the thread that locked can lock again indefinitely), I'm accepting you answer because of you second suggestion: a wrapper class. It's a good idea, but it shows how Nokia should have thought things out more.
Lucas
#2 is the state of art, #1 was "dirty hack" anways (and yes it ain't working for recursive, but I don't think it is do-able for recursive mutexes with the methods QMutex / QReadWriteLock provide).
penguinpower