| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 1 | |
Hello, I am using QThreads to have two processes running at the same time which can send signals to each other. This works perfectly fine, however, I have problems with the synchronization. The first thread is supposed to send a pointer to data to the second thread using SIGNAL/SLOT. The second thread uses this data and afterwards the first thread deletes the data. First, I tried sth like this: //Thread1: emit imageReady(image); //Thread2 displays the image delete image; The problem is now that if I use this like this, the image is deleted before the emitted function in Thread2 can actually use it - I get a segmentation fault. As a solution, I need a way to let the first thread wait for the SLOT-function in the second thread end. So I thought of using a mutex object to block the first thread while the second performed. I ended up with sth like this: //Thread1 QMutex mutex; emit imageReady(image,&mutex); mutex.lock(); //Thread2 in the SLOT function I then used QMutexLocker(mutex); Unfortunately, I still have the same problem as before: When the emit-slot is not called before the mutex.lock() in Thread 1, it does not get hold of the mutex and the program crashed once more. Do you have any ideas how to let the first thread wait for the second to end its called SLOT function? Any help is highly appreciated, I have been trying for a while.. Thanks in advance and greetings, Tim -- [ signature omitted ]
Tim Kietzmann wrote: > Hello, > > I am using QThreads to have two processes running at the same time > which can send signals to each other. This works perfectly fine, > however, I have problems with the synchronization. > > The first thread is supposed to send a pointer to data to the second > thread using SIGNAL/SLOT. The second thread uses this data and > afterwards the first thread deletes the data. Is there a reason you can't have the second thread delete the data when it's finished? Or possibly use a wait condition to signal that a thread is done with the image. Then have the first thread wait on that condition, and have the second call wakeAll when it's finished with the image. The first thread can then wake up and delete it. Darrik -- [ signature omitted ]
Em Thursday 01 November 2007 16:24:56 Tim Kietzmann escreveu: > I am using QThreads to have two processes running at the same time > which can send signals to each other. This works perfectly fine, > however, I have problems with the synchronization. > > The first thread is supposed to send a pointer to data to the second > thread using SIGNAL/SLOT. The second thread uses this data and > afterwards the first thread deletes the data. > > First, I tried sth like this: > > //Thread1: > emit imageReady(image); //Thread2 displays the image > delete image; If you upgrade to Qt 4.3, you can use the Qt::BlockingQueuedConnection signal-slot connection type. That will make the Thread2's slot finish processing (i.e., return from the slot) before the emit line finishes. -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
On 01.11.07 17:40:52, Thiago Macieira wrote: > Em Thursday 01 November 2007 16:24:56 Tim Kietzmann escreveu: > > I am using QThreads to have two processes running at the same time > > which can send signals to each other. This works perfectly fine, > > however, I have problems with the synchronization. > > > > The first thread is supposed to send a pointer to data to the second > > thread using SIGNAL/SLOT. The second thread uses this data and > > afterwards the first thread deletes the data. > > > > First, I tried sth like this: > > > > //Thread1: > > emit imageReady(image); //Thread2 displays the image > > delete image; > > If you upgrade to Qt 4.3, you can use the Qt::BlockingQueuedConnection > signal-slot connection type. Sorry for stealing the thread a bit, but I've got one question regarding the blockingqueue connectiong: Does it also work between gui and non-gui thread, if my non-gui-thread doesn't run an even loop? Andreas -- [ signature omitted ]
Em Thursday 01 November 2007 16:55:58 Andreas Pakulat escreveu: > Does it also work between gui and non-gui thread, if my non-gui-thread > doesn't run an even loop? It works, but not how you're probably expecting. Like the DirectConnection, BlockingQueuedConnection will only return once the target slot has returned. In the mean time, the thread emitting the signal is suspended and will not deliver even the next slot. Now, it "works" if you don't have an event loop: it blocks until the slot returns. And here's the catch: if there's no event loop, the slot never called, therefore it never returns and, therefore, the calling thread blocks forever. However, if the target thread creates an event loop and exec()s it, the signal is then delivered and the emitting thread will continue. In other words: you can use BlockingQueuedConnection to send to a thread that hasn't created an event loop *yet*. That means you don't need to write synchronisation code to make sure the event loop has started. -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
On Donnerstag, 1. November 2007, Thiago Macieira wrote: > Em Thursday 01 November 2007 16:55:58 Andreas Pakulat escreveu: > > Does it also work between gui and non-gui thread, if my > > non-gui-thread doesn't run an even loop? > > It works, but not how you're probably expecting. > > Like the DirectConnection, BlockingQueuedConnection will only return > once the target slot has returned. In the mean time, the thread > emitting the signal is suspended and will not deliver even the next > slot. Thats exactly what I expected :) > Now, it "works" if you don't have an event loop: it blocks until the > slot returns. And here's the catch: if there's no event loop, the > slot never called, therefore it never returns and, therefore, the > calling thread blocks forever. Well, I said between non-gui-thread and gui-thread and I meant sending a signal from the non-gui-thread, so the event loop will certainly run in my case - no matter what. Wow, that makes my current code again a bit easier, thanks TT :) Andreas -- [ signature omitted ]
Andreas Pakulat wrote: >Wow, that makes my current code again a bit easier, thanks TT :) I wanted to add a SynchronousConnection mode, which is DirectConnection for same-thread but BlockingQueuedConnection for cross-thread signal emission. However, there's a problem if the object you're sending a message to is moving to your thread. It deadlocks as well, so there's no advantage to BlockingQueuedConnection. -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
Hi Tim, On Thursday 01 November 2007, Tim Kietzmann wrote: > Hello, > > I am using QThreads to have two processes running at the same time > which can send signals to each other. This works perfectly fine, > however, I have problems with the synchronization. > > The first thread is supposed to send a pointer to data to the second > thread using SIGNAL/SLOT. The second thread uses this data and > afterwards the first thread deletes the data. > > First, I tried sth like this: > > //Thread1: > emit imageReady(image); //Thread2 displays the image > delete image; The problem here is that signal/slots working across threads use queued connections. This means that first of all your receiver thread *must* have its event loop running (by calling exec()) and that you cannot predict exactly when the second thread will call the slot as it depend upon how many other events it is processing. In the above code the emit call returns immediately as it just queues up an event in thread 2's event list. Ways around this are to simply get thread 2 to delete the data when it is done with it, or to get thread 2 to emit another signal e.g. finishedWithData() which calls a slot on thread 1 which can then delete the data. Although this seems unnecessary. Hope this helps, Sean -- [ signature omitted ]
On 01.11.07 16:24:56, Tim Kietzmann wrote: > I am using QThreads to have two processes running at the same time > which can send signals to each other. This works perfectly fine, > however, I have problems with the synchronization. > > The first thread is supposed to send a pointer to data to the second > thread using SIGNAL/SLOT. The second thread uses this data and > afterwards the first thread deletes the data. > > First, I tried sth like this: > > //Thread1: > emit imageReady(image); //Thread2 displays the image > delete image; > > The problem is now that if I use this like this, the image is deleted > before the emitted function in Thread2 can actually use it - I get a > segmentation fault. As a solution, I need a way to let the first > thread wait for the SLOT-function in the second thread end. That can only happen if you send around a pointer to the image instead of a copy. So one possible fix is to let the signal take a copy of the image and make sure its a deep copy. > So I thought of using a mutex object to block the first thread while > the second performed. I ended up with sth like this: Mutex is the wrong thing for synchronization, either use a QWaitCondition or a QSemaphore. A Mutex just makes sure that only 1 therad can access a certain routine at a time. Another option to fix this is don't send the image at all. It seems your two threads know about each other so its not a problem to store the image as member variable of thread one, provide three accessor methods (getImage,setImage and deleteImage) and protect each ones code with a QMutexLocker. Then thread 1 sets the image before emitting the signal, thread 2 gets the image and when its done processing it it deletes it. If you don't want the two threads to know anything about each other you need to emit a deep copy of the image. Oh, and of course make sure you have QueuedConnections between the threads and not direct connections. Andreas -- [ signature omitted ]
Tim Kietzmann wrote:
> First, I tried sth like this:
>
> //Thread1:
> emit imageReady(image); //Thread2 displays the image
> delete image;
>
> The problem is now that if I use this like this, the image is deleted
> before the emitted function in Thread2 can actually use it - I get a
> segmentation fault. As a solution, I need a way to let the first
> thread wait for the SLOT-function in the second thread end.
Is there any particular reason why 'image' is a pointer? Or an even better
question, why does the signal have to pass by pointer? If you are using QImage
(which is implicitly shared and cheap to copy), you could make the signal emit
by reference or value, e.g.:
void imageReady(const QImage &image);
Your slot would also have to get the image by reference or value. Then when
you emit:
emit imageReady(*image);
delete image;
For all the queued connections, Qt will automatically copy the image when
posting the event to the receiver objects. The only thing you have to do is
tell Qt how to make a copy of the image:
qRegisterMetaType<QImage>("QImage");
(See also examples/thread/mandelbrot/..., which does exactly this.)
--
[ signature omitted ]