Is it necessary to synchronise results passed across threads with signals?
-
Hi,
My program loads a file in my file loader object. I move the file loader object to a different thread, so it does not block the UI thread. the file loader emits signals about the progress of the loading, and eventually emits a 'load complete' signal which passes a pointer reference to an object representing the contents of that file. This signal is of the form:
@signals:
DataSetLoaded(DataSet *dataSet)@I'm wondering if I need to do any synchronization before I read the dataSet object from the main thread, or does the cross thread Qt signal/slot thing do that for me automagically? or do I need to do it myself in the case of pointers?
I'm not doing it now, and it works for me, but I have had some reports of crashes which would be consistent with a race condition from failed synchronization.
with thanks
-
Hi,
You have to do synchronization if your threads are both accessing a same resource at the same time. I guess once your loading thread emit the signal with the dataset as argument, the loading process is finished, and the thread will not access the data anymore? In such a case, you don't need to do synchronization because there is no concurrent access on a same resource. If your loading thread can still access the dataset, you should consider using QMutex.
-
Hi,
You are passing a pointer to a "remote" object and you access it from several thread. Then yes, you have to protect the access to that object. Qt's signals & slots won't help in this case.
-
bq. I guess once your loading thread emit the signal with the dataset as argument, the loading process is finished, and the thread will not access the data anymore? In such a case, you don’t need to do synchronization because there is no concurrent access on a same resource.
I think that there still needs to be a single synchronization step between the two threads when the signal is emited to ensure they see the same thing in memory (even in the absence of concurrent access). I'm wondering if this is provided automatically by Qt.
Once the DataSetLoaded(DataSet *dataSet) signal is emitted, the loader thread no longer touches the dataSet object, so there is no need for ongoing synchronization.
-
If you can guarantee that your code has no concurrent access, then you don't have to worry about synchronizing anything.
Anyway, Qt copies the signal parameters from the signalling thread into the slot thread safely. It does this by using queued connections. See the "ConnectionType":http://qt-project.org/doc/qt-5/qt.html#ConnectionType-enum documentation.
You might also be interested in reading the "Synchronizing Threads":http://qt-project.org/doc/qt-5/threads-synchronizing.html article.
[quote author="lisabeeren" date="1410876476"]I think that there still needs to be a single synchronization step between the two threads when the signal is emited to ensure they see the same thing in memory (even in the absence of concurrent access).[/quote]No need. The slot will only see your DataSet pointer after you emit the signal. Just make sure you don't change the DataSet object after you emit the signal -- then your slot will always see the final values in the DataSet.