Max Beikirch
Max Beikirch

Reputation: 2133

Qt synchronization impossible here?

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

Answers (2)

Kerrek SB
Kerrek SB

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

Chris
Chris

Reputation: 17535

You're looking for QMutexLocker

{
    QMutexLocker locker(&mut);
    ...
}

// Goes out of scope, unlocks the mutex in its destructor

Upvotes: 7

Related Questions