An event loop is local to a thread. Each thread may or may not be running an event loop, independently of the other threads. Each QObject is associated with a thread, which you can get with QObject::thread(). When a signal S of an object A is emitted whilst connected to a slot T of an object B, the following happens:
- if the connection is direct, then the thread emitting S executes T (this is more or less a function call with some overhead);
- if the connection is queued, then a message is queued in B->thread()'s event loop, and B->thread() will eventually execute T;
- if the connection is automatic (the default), then it behaves as a direct connection if A->thread() == B->thread(), or as a queued connection otherwise.
An object's thread is initially set to the thread executing its constructor. You can change it later on with QObject::moveToThread().
Here is what happens in your program. Let us call the main thread M and the thread managed by the QThread N.
Since you construct the QTcpSocket in your QThread's run() method, its thread() is N. You then connect the socket's readyRead() signal to the QThread's data_ready() slot using an automatic connection. Since the socket lives in N and the QThread lives in M, the connection behaves as a queued connection and M executes data_ready(). In order to read from the socket in N, all you have to do is move data_ready() to a custom QObject created in the QThread's run(). For example :
Q_OBJECT
...
public slots:
void data_ready();
...
}
void server_thread::run() {
MyObject o;
connect(&socket, &QTcpSocket::readyRead, &o, &MyObject::data_ready);
...
exec();
...
}
class MyObject : public QObject {
Q_OBJECT
...
public slots:
void data_ready();
...
}
void server_thread::run() {
QTcpSocket socket;
MyObject o;
connect(&socket, &QTcpSocket::readyRead, &o, &MyObject::data_ready);
...
exec();
...
}
To copy to clipboard, switch view to plain text mode
If server_thread::run() does not do anything clever beyond creating the objects, setting up the connections and running exec(), you need not subclass QThread. Instead you can do the following:
/* Members of some class, e.g. a main window */
MyObject o;
...
void setup() {
connect(&socket, &QTcpSocket::readyRead, &o, &MyObject::data_ready);
socket.moveToThread(&t);
o.moveToThread(&t);
...
t.start();
...
}
/* Members of some class, e.g. a main window */
QThread t;
QTcpSocket socket;
MyObject o;
...
void setup() {
connect(&socket, &QTcpSocket::readyRead, &o, &MyObject::data_ready);
socket.moveToThread(&t);
o.moveToThread(&t);
...
t.start();
...
}
To copy to clipboard, switch view to plain text mode
If I were you, I would try doing all the networking in the main thread and only do the heavy computation in another thread. You would not even need to worry about synchronization and the overhead of thread creation: QtConcurrent::run() would probably do just what you want with good performance (threads are recycled).
Bookmarks