[Qt-interest] Can I use QWaitCondition this way? How could it work reliably?

ammo ammonite99 at googlemail.com
Wed Nov 9 17:34:19 CET 2011


Hi all,
so what i want to to was:
1. a socket only receives messages from his partner.
2. this socket works in a thread
3. the partner closes the connection (hence the thread in which the
socket works) by sending of two bytes "BR"

I did't want to use waitForReadyRead, so i tried with QWaitCondition.
first of all, if the partner requests the connection, i create a
socket in an overridden function of incomingConnection from
QTcpServer, just like this:
*************************************************************************************************
QTcpSocket* socket = new QTcpSocket;
if (!socket->setSocketDescriptor(desc)) return;
Worker* worker = new Worker(socket, this);

connect(socket, SIGNAL(readyRead()), worker, SLOT(data_available()));
connect(socket, SIGNAL(disconnected()), worker, SLOT(c_disc()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));	
worker->start();
*************************************************************************************************

the class Worker ist the thread where the socket works. and this class
seems like this:

*******************************beginning of
worker.h*******************************************************
class Worker: public QThread
{
Q_OBJECT
public:
 Worker(QTcpSocket* socket, QObject* parent = 0);
 virtual ~Worker();
 void run();
private:
 QTcpSocket*		socket;
 QMutex			mutex;
 QWaitCondition	cond;
 bool			quit_ready;
public slots:	
 void data_available();
 void c_disc();
};
*******************************end of
worker.h*******************************************************

so, the ideal is, the thread Work tries to wait on the wait condition
(the partner is sending something or the connection is closed), so the
implemetation as follows:

*******************************beginning of
worker.h*******************************************************
Worker::Worker(QTcpSocket* socket, QObject* parent)
{
	quit_ready = false;
	this->socket = socket;	
}

Worker::~Worker()
{

mutex.lock();
quit_ready = true;
cond.wakeOne();
mutex.unlock();


wait();
if (socket) delete socket;	
}

void Worker::data_available()
{		
QMutexLocker locker(&mutex);
cond.wakeOne();
}

void Worker::c_disc()
{
QMutexLocker locker(&mutex);
quit_ready = true;
cond.wakeOne();
}

void Worker::run()
{


	bool should_quit;
	bool should_read;
	QDataStream in(socket);
	in.setVersion(QDataStream::Qt_4_0);


	for (;;) {
		
				
		should_read = socket->bytesAvailable();
		
		mutex.lock();
		should_quit = quit_ready;

		if (!should_quit && !should_read) {
			cond.wait(&mutex, 12000);
		}
		should_quit = quit_ready;				
		mutex.unlock();
		should_read = socket->bytesAvailable();

		if (!should_quit && !should_read) { qDebug() << "exit0"; goto out; }


		while (socket->bytesAvailable() > 0) {
			QByteArray ba;
			while (ba.size() < 3) {
				quint8 ch;								
				if (!socket->bytesAvailable() &&
					!socket->waitForReadyRead(2000)) { qDebug() << "error1"; goto out; }			
				in >> ch;
				ba.append(ch);
			}


			qint64 b_size = ( //first of all to get the size of message sent by
partner, 3 bytes.
				(quint8(ba.at(0)) << 16) |
				(quint8(ba.at(1)) << 8) |
				(quint8(ba.at(2))));


			QByteArray msg;
			while (msg.size() < b_size) {
				quint8 ch;							
				if (!socket->bytesAvailable() &&
					!socket->waitForReadyRead(2000)) { qDebug() << "error2"; goto out; }
				in >> ch;
				msg.append(ch);
			}
			
			if (msg == QString("BR")) {
				goto out;
			}	
		}

		if (should_quit) goto out;
	}

out:
	qDebug() << "out";
}
*******************************end of
worker.cpp*******************************************************

So the result is, the class Worker works fine, mostly. but sometimes i
get an error:
Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt. You must
reimplement QApplication::notify() and catch all exceptions there.

Could someone help me, i could understand what goes wrong here. this
error happens very rarely, but it really happens. I've tried to find
out the reason since a week...thus many thanks if someone knows how
can i do this correctly.

Henning



More information about the Qt-interest-old mailing list