[Qt-interest] FW: ASSERT failure in QMutex::unlock(): "A mutex must be unlocked in the same thread that locked it."

Sarvesh Saran Sarvesh.Saran at synopsys.com
Sun Jul 18 13:27:51 CEST 2010


Hi,

Thanks for that clear explanation. 

Kindly let me know if what I am doing below is correct...

My main purpose behind exploring QThreads is that my application connects to multiple servers, receives messages and does a lot of message processing for each message.

I would like to create threads to handle this, one for each server. Each QThread would connect to a server, receive streaming messages, parse them and simply send an update to the Main Thread  ( which will use these updates to populate a QTreeWidget). Because each server sends a lot of messages it makes sense to have a separate thread handling the server.

//In the main Window: 

MainWindow::startThreads() {

For each server {
MyThread *th = new QThread(this);
connect(this,SIGNAL(stop()),th,SLOT(stopped()));
connect(th,SIGNAL(sendServerStatus(QString)),this,SLOT(updateServerStatus(QString))); //update a tree widget
connect(th,SIGNAL(sendServerTaskStatus(QString)),this,SLOT(updateTaskStatus(QString))); //update a tree widget
....
....
....
th->start(); 
}
}


//MyThread code:

MyThread:run() //I hope this will be  executed in a different flow i.e. thread ?
{
	QString msg;
	QString status;
	//create a server connection object (srv points to it)
	//receive messages 
	while(allowed_to_run() && server_gets(srv,&msg) == 0) {  //we normally get thousands of messages here
	//identify message type and contents(status in this ex)
	//send an update back to the main thread e.g.:
	emit sendServerStatus(status); //this will cause the slot in mainwindow to get executed by the main window?
	}
	
}

It is important for me that the MainWindow should remain responsive while all this is happening....but as the number of connected servers goes up, the main window starts consuming more and more CPU..

Things get worse when the server (which is a QProcess) is also started by the MainWindow....in this case each server object also belongs to the main window..in this case MainWindow gets stuck for > 2 servers..

I would welcome ideas on how I can handle all this without the main window become unresponsive..


Thanks!
Sarvesh



-----Original Message-----
From: qt-interest-bounces at trolltech.com [mailto:qt-interest-bounces at trolltech.com] On Behalf Of Sean Harmer
Sent: Friday, July 16, 2010 11:54 PM
To: qt-interest at trolltech.com
Subject: Re: [Qt-interest] ASSERT failure in QMutex::unlock(): "A mutex must be unlocked in the same thread that locked it."

On 16/07/2010 17:36, Sarvesh Saran wrote:
> Hi,
>
> Sorry for the poor indentation. Let me rephrase:
>
> I am simply having a tough time understanding how signals and slots work across threads.
>
> Assume that I have a MyThread:QThread object called A running and it contains a public slot setValue().
>
> //this code is in the main window
> MyThread *a = new MyThread; //create the thread
> connect(this,sendValue(int),a,setValue(int)));
>
> later in the code I emit a signal:
> emit sendValue(10);
>
> I would like to know how this emit is different from:
> a->setValue(10) ?
>
> in either case, who executes the slot setValue? Is it the MainWindow thread  or MyThread?

The slot gets executed in the thread that calls a->setValue(10) and emit 
sendValue(10), the main thread in your case.

This is because the QThread object has affinity with the main thread 
because that is where it was created.

To ensure that your slot gets executed in the context of yoru worker 
thread, you should not put the slot on the QThread object itself, but 
rather create a new helper object derived from QObject (with 0 for the 
parent) in the run() function of your thread class.

This new QObject will have affinity with the worker thread because that 
is the context in which it was created.

So now if you make a connection between a signal from an object that has 
affinity with the main thread (your mainwindow object for example) and a 
slot on the new helper object in your worker thread, the default 
connection mode of Qt::AutoConnection will determine that Qt should use 
a queued connection for this case. [In actual fact the decision is 
deferred until you emit the signal since objects can change thread 
affinity with the moveToThread() call].

For your worker thread to be able to deliver the event that is used to 
implement queued connections, you must ensure that you start the event 
loop by calling QThread::exec() within the run() function. Without this, 
your helper QObject that lives in the worker thread will not have its 
slot called.

In summary, it is best to consider QThread purely as a means of 
launching another thread, not as the object that does any real work in 
that thread (unless you do not need the worker thread to be event driven 
of course as illustrated in the Mandelbrot example). Much better to 
create QObjects within the worker thread to do the work instead.

HTH,

Sean

_______________________________________________
Qt-interest mailing list
Qt-interest at trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-interest




More information about the Qt-interest-old mailing list