Reputation: 19100
I have a worker thread, which sends some data over TCP, taking that data from several other threads. I need to fill some data, having sort of a mutex over it, and then call another thread's method, which would then unlock the mutex when finished while caller thread would continue its own job.
I've first implemented this using Qt as follows:
Data globalData;
QMutex mutex;
void requestSend() // several such functions in other threads
{
mutex.lock(); // we want to change the data
globalData=fillData();
invokeMethod(workerClass,"work",Qt::QueuedConnection);
}
void work() // a slot in a class instanced in worker thread
{
sendData(globalData);
mutex.unlock(); // data is now available to be changed
}
This seems reasonable and even works, but then I found this in the QMutex documentation:
void QMutex::unlock ()
Unlocks the mutex. Attempting to unlock a mutex in a different thread to the one that locked it results in an error. Unlocking a mutex that is not locked results in undefined behavior.
I have two questions:
What's the reason of such restriction to unlock in a different thread? (and why don't I see the error the doc says about?)
What should I use instead of QMutex to achieve what I'm trying to? Would QWaitCondition be an adequate replacement?
Upvotes: 0
Views: 108
Reputation: 27611
The purpose of the mutex is to ensure that only one thread can access the data at any one time. Therefore, it doesn't really make sense to lock in one thread and unlock the same mutex in another.
If you're finding it works, you're probably just lucky at the moment, but doesn't mean it won't cause you issues if the timing of threads changes.
I'm not quite sure exactly what you're trying to do, but it appears that you have various threads that can write to the globalData and as soon as you write to it, you want another thread to send the data before more data writes to the globalData.
What I suggest is to create a mutex around the writing of the data and just call a signal to send the data to the thread that will send the data. Being on different threads, the data will be copied anyway: -
void requestSend() // several such functions in other threads
{
QMutexLocker locker(&mutex);
globalData=fillData();
emit SendData(globalData); // send signal to the thread which will send the data
}
Note that QMutexLocker is used to ensure the lock is released, even if an exception should occur.
Don't be too concerned about the copying of data in signals and slots; Qt is very efficient, and will only create a "copy on write", due to implicit sharing, if you use its container objects. Even if it has to make the copy for passing the data between the threads, you shouldn't really worry about it, unless you can see a performance issue.
Finally, note that implicit sharing and multithreading can work happily together, as you can read here.
Upvotes: 1