Reputation: 2133
Consider the following situation:
class SomeClass : public QObject
{
Q_OBJECT
private:
unsigned long long someVar;
public:
unsigned long long getSomeVar(){
return someVar;
void threadFunc();
}
threadFunc()
will be invoked in a new thread (you guessed it), and it will look like this:
void SomeClass::threadFunc()
{
++someVar;
// Do stuff...
}
Now, in another thread, I want to read someVar
. I do so by calling getSomeVar()
. However, synchronization is needed. How do I do that? For the thread that posesses somevar
, synchronization is not hard. It'll just be
void SomeClass::threadFunc()
{
mut.lock();
++someVar;
mut.unlock();
// Do stuff...
}
with a QMutex mut
added in the class declaration. But how do I synchronize getSomeVar()
? I can't just say:
unsigned long long getSomeVar(){
mut.lock();
return someVar;
mut.unlock();
}
mut.unlock()
will never be called because of the return
-statement before.
I know that usually such conflicts are avoided by writing...
unsigned long long getSomeVar(){
QMutex mut;
// mut-constructor calls mut.lock()
return someVar;
// mut-destructor calls mut.unlock()
}
... but in this case, I need the mutex to be the same inside getSomeVar()
and threadFunc()
. I tried
unsigned long long getSomeVar(){
// constructing mutex from mut (which is the class' mutex)
QMutex mutex(mut);
// mutex-constructor calls mut.lock()
return someVar;
// mutex-destructor calls mut.unlock()
}
but the copy-constructor of mutex is private.
What can I do here?
Upvotes: 2
Views: 224
Reputation: 476940
You're confusing the mutex with the lock: There's only one mutex per guardable variable, but there may be many attempts to lock it!
You need a separate lock class, of which you have one instance per thread:
struct Lock
{
QMutex & m_;
Lock(QMutex & m) : m_(m) { m_.lock(); }
~Lock() { m_.unlock();}
};
Usage:
QMutex mutex;
void thread_function()
{
Lock lk(mut);
critical_operation();
} // unlocks "mutex" as if by magic
Qt probably already provides such a class for your. (The standard library does so, too: for std::mutex
you have std::lock_guard<std::mutex>
.)
Upvotes: 2
Reputation: 17535
You're looking for QMutexLocker
{
QMutexLocker locker(&mut);
...
}
// Goes out of scope, unlocks the mutex in its destructor
Upvotes: 7