1

Although I have a fair amount of understanding of QObject, QThread and how to multi thread in Qt, I am having trouble understanding some of the scenarios. Consider a class Myclass : QObject which is moved to another QThread.

class MyClass : QObject
{
public slots:
    void slot1();
    bool slot2();
    void slot3(); 
}

I have a class

class Window
{
signals:
    void sig1();
    bool sig2();

private:
    MyClass *myObj;

public:
void func()
{
    connect(this, SIGNAL(sig1()), myObj, SLOT(slot1()), Qt::DirectConnection);
    emit sig1();
    qDebug("SIGNAL1 emitted!");

    connect(this, SIGNAL(sig2(bool)), myObj, SLOT(slot2(bool)));
    bool result = emit sig2();

    myObj->slot3();
}

}
  1. When sig1 is emitted I understand that the qDebug() will be executed only after slot1() is executed. But is slot1 executed in Window thread or MyClass thread?

  2. In case of sig2 is it guaranteed that result will store value returned by slot2 or is it necessary for this connection to be direct?

  3. Is it correct to run slot3 as shown? slot3 modifies class variables of myObj as well as it emits a SIGNAL which is connected to a SLOT of the calling Window object. If it is correct then when will the slot of Window be executed and in which thread?

Cool_Coder
  • 4,888
  • 16
  • 57
  • 99

2 Answers2

2

When sig1 is emitted I understand that the qDebug() will be executed only after slot1() is executed.

It is not guaranteed by default. The slot will be called whenever the Qt event loop calls it back which can be either before a function or method or after that is after the connect statement. If you specify the direct connection for the last parameter, Qt::ConnectionType`, then the immediate call will be guaranteed. See the documentation for details:

Qt::DirectConnection 1 The slot is invoked immediately, when the signal is emitted.

However, Qt::AutoConnection is default if you do not specify it explicitly.

But is slot1 executed in Window thread or MyClass thread?

It depends on the connection type parameter again. See the documentation for details.

In short, if it is queued, it is executed in the receiver's thread, otherwise from a different thread than the receiver's.

In case of sig2 is it guaranteed that result will store value returned by slot2 or is it necessary for this connection to be direct?

This does not look right. Signals meant to be avoid, and you cannot store their return value as a function or method return value expecting that it is the result of the connected slot.

Even if you could, it would be confusing as more than one slot can be connected to the same signal. Even more, signal can be connected to signals.

Is it correct to run slot3 as shown? slot3 modifies class variables of myObj as well as it emits a SIGNAL which is connected to a SLOT of the calling Window object. If it is correct then when will the slot of Window be executed and in which thread?

Yes, you can call it like that since slots are just regular functions, usually with a void return value type.

László Papp
  • 51,870
  • 39
  • 111
  • 135
  • 1. sig1 is connected by direct connection already as shown in code. Is there something I am missing here? The documentation does not state in which thread the SLOT will be executed in case of direct connection. 2. If it is incorrect to accept return value from a SIGNAL then why does a SIGNAL have data type? Morover the said code is compiling and running but I am unable to guaranty what is happening behind. 3. I was curious because myObj is moved to different thread and may not be called from another thread. – Cool_Coder Dec 25 '13 at 16:29
  • @Cool_Coder: So, in order... 1) I did not mention what you set. I was talking about it in general from which you can draw your conclusion. Moreover, it does guarantee it is not in the receiver's thread as per my answer and the official documentation, if it is not queued. 2) Because signal is just a regular function declaration, it has to have a return value, but it has no meaning, really. 3) I am not sure I understand what you are trying to say. – László Papp Dec 25 '13 at 16:39
  • 1. This mean that the way slot1 & slot3 are executed by Qt are pretty much the same. So is it better to execute the way slot3 is executed instead of the way slot1 is executed? – Cool_Coder Dec 25 '13 at 16:43
  • 1
    @Cool_Coder: it depends on the use case. Say, you have a library and a separate application. The slot would be in the application, but the signal is emitted in the library. In that case, the library is not aware of the application's slot to call directly, so you do need to connect. If your maintained software is responsible for both, and it does not have to be going through the signal, then you can call directly, yes. Note that you are asking at least the fourth separate question in the same thread. It is really bad to bomb one thread with so many questions. – László Papp Dec 25 '13 at 16:45
  • 3. I meant that since myObj is moved to a thread, I believed accessing class members from another thread (via function) should be bad. – Cool_Coder Dec 25 '13 at 16:45
  • @Cool_Coder: that also depends on the exact scenario, but it is the 5th question... :) – László Papp Dec 25 '13 at 16:47
  • Looks like I have a lot of confusion on this topic, Thanks for clearing some. Can you please give me some RELIABLE references on this topic. The Qt documentation falls short in this are IMHO. – Cool_Coder Dec 25 '13 at 16:49
  • @Cool_Coder: I am afraid, I do not know anything more authoritative than the Qt documentation for this except the source code itself for sure. – László Papp Dec 25 '13 at 16:51
  • I was discouraged to call functions directly as in slot3 in an answer here: http://stackoverflow.com/a/18876716/982049. This is how my confusion started. – Cool_Coder Dec 25 '13 at 16:53
  • @Cool_Coder: right, so in general, it is better to avoid calling into a different thread. One reason I can think of, is because they may operate on different "local thread data" which will not be what you expect it to be as the behavior. There are rare cases where it is not a concern, but as a rule of thumb: try to avoid it when possible. – László Papp Dec 25 '13 at 16:57
1

For question #1. If you did not force the DirectConnection by default slot 1 will be executed in the thread that contains MyClass sometime in the near future. The way this works is the signal / slots by default will use a QueuedConnection for cross thread signals and slots.

Also your

qDebug("SIGNAL1 emitted!");

is not guaranteed to be executed after slot1() executes by default. If the thread containing your MyClass object is busy the execution of slot1() will be delayed().

However since you forced the DirectConnection slot1() will execute in the thread that emits the signal and it will also be gauranteed to execute before qDebug returns.

For question #2. I believe the connection needs to be direct for the value of the result to be correctly returned. I believe you had to force the direct connection for that to work. And also remember that forcing the DirectConnection means that the execution of the slot will happen in the thread that emits the signal not the thread that owns MyClass. I believe the documentation discourages the usage of return values from slots so I have never done this in production code. One reason for not using return values is the confusing behavior if more than 1 slot is attached to the same signal.

For question #3. You can do this but remember that the code will be executed in the current thread not the thread that owns the MyClass.

drescherjm
  • 10,365
  • 5
  • 44
  • 64