3

I was going through the links

  1. You are doing it wrong
  2. Using QThread in right way Part1
  3. Using QThread in right way Part2

I got confused by some statements. In the first link, it says that

all of the functions in QThread were written and intended to be called from the creating thread, not the thread that QThread starts.

while it suggests to use moveToThread to move an object to new thread, instead of subclassing QThread. My question is:

The default implementation of run method calls exec, which creates an event loop, and when an object's thread affinity is changed using moveToThread, all the slots will be executed in the new thread, not on the creating thread, which is contradictory with the aforementioned intended use. Am I missing something?

Second question:

In the third link it is said

event queue is belong to thread instead of event loop, and it’s shared by all the event loops running in this thread.

My question is how there can be more than one event loop in a single thread ? What I understand is, event-loop loop through the event-queue, until exit/terminate is called, and processes each event arrives on that queue. If this is true, one loop will never end (unless exit/terminate is called), how another can begin? Any sample code demonstrating it will be highly appreciated.

Rakib
  • 7,435
  • 7
  • 29
  • 45
  • You missed out "How To Really, Truly Use QThreads; The Full Explanation" : http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ – TheDarkKnight May 29 '14 at 10:59
  • @Merlin069, I studied it, but did not mention, it is not relevant to my questions. – Rakib May 29 '14 at 11:59
  • Sorry, I didn't have time to answer then. – TheDarkKnight May 29 '14 at 12:58
  • Whoever down-voted this question, please explain why. – TheDarkKnight May 29 '14 at 13:00
  • 1
    It is suggested to move objects **other than `QThread`** to the thread. Thus no `QThread` methods other than `run` execute in the new thread. – Kuba hasn't forgotten Monica May 29 '14 at 18:23
  • Exactly what Kuba said. The statement `all of the functions in QThread were written and intended to be called from the creating thread, not the thread that QThread starts.` basically means do not do this: `moveToThread(this);`. – thuga May 30 '14 at 07:46

1 Answers1

5

"which is contradictory with the aforementioned intended use. Am I missing something?"

Yes, I think you're misunderstanding the concept of thread affinity (the thread on which an object is running).

Let's take an example with minimal code: -

QThread* pThread = new QThread; // QThread on the main thread
MyObject* myObj = new MyObject; // MyObject on the main thread
myObj->moveToThread(pThread);   // MyObject on the new thread, controlled by pThread
pThread->start();               // pThread instance is still on the main thread

Assuming this code has been created from an object whose thread affinity is the main thread, such as QMainWindow, the thread object pThread is running on the main thread; it's thread affinity is the main thread.

In contrast, the QObject derived MyObject instance, myObj, has been moved to the new thread pThread. So, the thread affinity of myObj is now the new thread.

The "functions written for QThread" are still called directly from the main thread, as that's where it's running.

Think of QThread as a thread controller object, rather than the thread itself. This is one of the reasons why it is often discouraged to inherit from QThread, unless you want to change how QThread manages the underlying thread.

how there can be more than one event loop in a single thread ?...

I've not used this directly myself, but I'll try to explain this as I understand it. Perhaps someone else will be able to correct or confirm this. From the Qt Documentation for QEventLoop, it states: -

At any time, you can create a QEventLoop object and call exec() on it to start a local event loop.

The signature from QEventLoop exec is: -

int QEventLoop::exec ( ProcessEventsFlags flags = AllEvents )

So if you pass in a set of flags, only these events would be handled. Now, as calling exec() starts the processing of events until exit() is called, you can create a local event loop that lets your program wait until one or more specific events occur.

A second event loop is a local event loop within the main event loop, but as each event loop can process the whole event queue, which is shared by all event loops in a thread, it can be used to override event handling from the main event loop.

If you conceptualise an event loop as doing something like this (pseudo code): -

QList<QEvent*> eventList;
while(!stop)
{
    // handle events in eventList
}

A 2nd event loop would then do this: -

bool bStop = false;
QList<QEvent*> eventList;
while(!bStop)
{
    // handle events in eventList
    ...
    ...
    // Inner event loop
    bool bStop = false;
    while(!bStop)
    {
        // handle events in eventList
    }
}
TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85
  • Thanks for your input. The first question remains yet, if my understanding is correct, than the article is contradicting itself. But your answer for second question was really helpful. +1 – Rakib May 29 '14 at 16:05
  • Can you please explain where you see a contradiction? The intended use of the QThread is that its functions are called from the thread of its object creation, whereas the functions of the object moved to that thread are run and called in the new thread. – TheDarkKnight May 29 '14 at 16:29
  • your last comment actually clarified my confusion. – Rakib May 30 '14 at 12:37