25

Qt documentation states that it is possible to connect two signals together:

It is even possible to connect a signal directly to another signal.

I tried:

connect(x, SIGNAL(S()), y, SIGNAL(func()));

and it works as mentioned, but Qt documentation continues:

(This will emit the second signal immediately whenever the first is emitted.)

Does this mean that QueuedConnection will not work correctly? Can I connect two signals across threads?

The reason I am asking this is because I solved a class of crashes on an application by avoiding this, but I am not sure if this was related to connecting signals together.

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
dashesy
  • 2,596
  • 3
  • 45
  • 61
  • 2
    Have you tried creating a test case of cross-threaded signal-signal connections? Print a message before and after the original signal (in one thread), and in a slot connected to the second signal (in a second thread). In the second thread, repeatedly call a `sleep` that lasts a second or two in the event loop, to make it more obvious that the slot in that thread is being called either synchronously with the first thread, or asynchronously in the second thread. – tmpearce Mar 21 '12 at 04:22
  • @tmpearce- good advice, I will try it and post the result here – dashesy Mar 21 '12 at 14:47
  • 2
    So, did you ever try it? – gnovice Feb 12 '13 at 18:40
  • The documentation is worded poorly. QueuedConnection will queue connections as it should. Source: Personal experience. I've used SIGNAL/SIGNAL connections across thread boundaries quite a bit. – cgmb Mar 13 '13 at 00:31
  • @Slavik81 - I think personal experience (i.e. something tested) is as good as of an answer here, I appreciate if you do post that as answer. – dashesy Mar 13 '13 at 14:01

2 Answers2

29

It shouldn't be a great deal different from a signal/slot connection. Let's take a look at underlying mechanism of signals/slots. There is an event queue in each thread which maintains signals (events) that have been emitted but not processed yet. So whenever the execution returns to the event loop the queue is processed. Event loop itself doesn't handle the events. Rather it delivers them to the objects so they can handle it. In this special case, I suppose that the object would emit another signal which would be inserted in the queue. When the execution returns to event loop the new signal is handled by the object again. Here is a test which proves the above argument.

If you run the codes attached, the output would be:

before signal() 
after signal() 
slot() called

which means defining a signal-signal connection type as queued between threads have the expected queued behaviour, that rejects the argument which it is always immediate. If you define it as direct, the output would be:

before signal()
slot() called 
after signal()

as expected. it doesn't generate any errors or warnings, and program doesn't crash as well.Yet this simple example doesn't prove it works for a large and complex one as well.

main.cpp:

#include <QtGui/QApplication>
#include "dialog.h"
#include "testssconnection.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    TestSignalSignalConnection * t = new TestSignalSignalConnection();
    t->start();

    return a.exec();
}

testssconnection.h:

#ifndef TESTSSCONNECTION_H
#define TESTSSCONNECTION_H

#include <QObject>
#include <QThread>

class TestSignalSignalConnection : public QThread
{
    Q_OBJECT
public:
    explicit TestSignalSignalConnection(QObject *parent = 0);

    void run();

signals:
    void signal1();
    void signal2();

public slots:
    void slot();
};

#endif // TESTSSCONNECTION_H

testssconnection.cpp:

#include "testssconnection.h"
#include <QtCore>

TestSignalSignalConnection::TestSignalSignalConnection(QObject *parent) :
    QThread(parent)
{
}

void TestSignalSignalConnection::run()
{
    TestSignalSignalConnection *t = new TestSignalSignalConnection();

    this->connect(this,SIGNAL(signal1()),t,SIGNAL(signal2()), Qt::QueuedConnection);
    t->connect(t,SIGNAL(signal2()), t,SLOT(slot()), Qt::DirectConnection);

    qDebug() << "before signal()";
    emit signal1();
    qDebug() << "after signal()";

    exec();
}

void TestSignalSignalConnection::slot()
{
    qDebug() << "slot() called";
}
Ameer Jewdaki
  • 1,758
  • 4
  • 21
  • 36
1

Take a look at qt-project, its a great wiki page about Threads and signals.

Threads, Events and QObjects::Signals and slots across threads

kikeenrique
  • 2,589
  • 2
  • 25
  • 46
  • 1
    Thanks for the link, but I was more looking for some example as a definite proof for future Googlers. – dashesy Mar 19 '13 at 01:20