Confusion regarding QThread, QObject, Thread Affinity and Event Loop - c++

I was going through the links
You are doing it wrong
Using QThread in right way Part1
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.

"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
}
}

Related

Qt moveToThread works only the first time

I'm creating an application performing an infinity task, so I decided to manage it with a QThread. On specific condition, this thread should spawns a temporary therad in order to perform some computation. The problem is that this works only the first time, while the second time I get this error:
QObject::moveToThread: Current thread (0xd29078) is not the object's thread (0x6e000df0).
Cannot move to target thread (0x6e002c68)
In the main I initialized the class and moved it in a QThread.
AccelerometerBuffer accBuffer;
QThread *accelerometerThread = new QThread;
accelerometerThread->setObjectName("AccelerometerThread");
accelerometerThread->setParent(&accBuffer);
accBuffer.moveToThread(accelerometerThread);
QObject::connect(accelerometerThread,SIGNAL(started()),&accBuffer,SLOT(readAccelerationData()));
QObject::connect(accelerometerThread,SIGNAL(finished()),accelerometerThread,SLOT(deleteLater()));
accelerometerThread->start();
In readAccelerationData, after condition, I should call another SLOT (saveData()) in the AccelerometerBuffer class and so the temporary thread should be spawned by the accelerometerThread.
if(condition){
QThread* thread = new QThread;
QThread::currentThread()->moveToThread(thread);
connect(thread,SIGNAL(started()),QThread::currentThread()->parent(),SLOT(saveData()));
connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
thread->start();
}
The first time that the condition occurs, everything works fine, saveData is correctly executed.
The following times, instead, I get the error and I don't understand the reason.
You can only moveToThread from the owning thread. As soon as your move to another thread, the same call will no longer be able to do anything.
From https://doc.qt.io/qt-5/qobject.html#moveToThread
Warning: This function is not thread-safe; the current thread must be same as the current thread affinity. In other words, this function can only "push" an object from the current thread to another thread, it cannot "pull" an object from any arbitrary thread to the current thread.

Is QThread::quit usabled from within the running thread

So I have the following situation:
I have a QThread that runs an eventloop (i.e. no custom run function). To stop the thread, I send a signal to a worker in that thread. This worker then does cleanups etc and at some point is done and quits the thread.
The problem I am facing right now is: If I invoke the workers stop method and then immediatly wait for the thread to finish it will never do so because the workers done signal does not get processed. Code:
class Worker {
signals:
void done();
public slots:
void stop() {
//dummy code to illustrate what happens here:
QTimer::singleShot(3000, this, &Worker::done);
}
};
// in the main thread
auto thread = new QThread();
auto worker = new Worker();
worker->moveToThread(thread);
connect(worker, &Worker::done, thread, &QThread::quit); //implicitly a queued connection
// ...
QMetaObject::invokeMethod(worker, "stop", Qt::QueuedConnection);
thread->wait(); //blocks here forever, because the connect is queued
Now reason the problem is obvious - Because I block on the main thread the slot can never be invoked (because queued connection) and thus quit is never called. However, if I simply call QThread::quit (or QThread::exit) directly from the worker (or use a DirectConnection) then there is no problem anymore because the eventloop of the main thread is no longer required to process the event.
So the actual question here is: Is that allowed? Can I call QThread::quit from within the actual thread? Or can this create Race conditions, deadlocks and other problems like that. The documentation does not mark the method as threadsafe - but the thread that is managed by QThread might be an exception.
If you look in the file src/corelib/thread/qthread.cpp in the Qt source folder, you can see how quit() is implemented:
void QThread::quit()
{ exit(); }
.... and QThread::exit() is definitely intended to be called from within the thread itself. So the answer is yes, it's fine to call quit() from within the QThread's thread (although it might be a bit more usual to just call QThread::exit() directly instead).
Can I call QThread::quit from within the actual thread?
The question is actually backwards!
Since this method controls the event loop, and the event loop most definitely runs on the thread, the default assumption is that it's not a thread-safe method and thus can only be called from within the thread, since it controls a QEventLoop instance instantiated via QThread::run. That event loop, and its event dispatcher, are QObjects and most definitely have their thread() equal to the QThread instance in question.
But that wouldn't make QThread very useful, and thus QAbstractEventDispatcher::exit, and thus QEventLoop::quit and QThread::quit, are indeed thread-safe methods - you can call them from wherever, including from threads other than the one where the event loop lives. Both the event loop and thread's methods take extra precautions to protect their state from races, so the "and thus" part a few sentences ago is hand-wavey a bit.

QThread: If there is no run() implemented, what does it do while waiting for signal?

First of all, I am not using a GUI. (In case that matters.) I want to send the path of a file to a thread (as char*), have it process the file, then return. Preferably, I would like the thread to stop when it's not being used.
The Qt documentation shows two approaches to creating threads:
Create a QObject and moveToThread().
Create a QThread then start() it when it's needed.
In the two approaches above, what is happening if I don't have a run() function? I don't have one because I don't see a way of passing the char* to run(), so I'm using a signal. Do I have to start() the thread in order for it to work properly? If so, what does this do if there is no run()? Can I just create it, connect the signals/slots, then call it when I need it? Does one of the above approaches offer an advantage in this case?
UPDATE: Thank you for the quick response Johannes Schaub and thuga.
If I'm using QObject->moveToThread(), that thread is then running in an event loop? And this event loop sleeps when there is no input? (If so, that's good.) The thread (event loop) is tied to QObject's signals and slots, right? So I need to then have this object's scope be the calling thread by putting it in the constructor? (And quit() wait() in the destructor) It therefore runs for the entire lifetime of the original thread?
I don't think I need to have a slot for the QThread, because I only want to invoke it, not communicate back and forth. (Except the finished signal.) So I would do something like this:
a. Create an instance of the QThread:
WorkerThread *workerThread = new WorkerThread(this);
b. Send it the string. This is the part I'm not sure about. I think Johannes tried to explain, but I'm still not clear. I can't send the filename via a signal/slot because QThreads shouldn't use slots. (but can in moveToThread() case because of queued connections)
c. Start the Thread with .start()
The default run function then calls exec, which enters an event loop. The loop sleeps if it doesnt have an event to process.
The object that you move to the thread is not the QThread object itself. It is another object. The QThread object itself just has the event loop and is still associated with the main thread (its affinity is the main thread).
If the thread operates in the background, you best use QString as the filename and then call a respective "processFile" function or similar of that object that you pass the file name. The invocation can either be by a signal slot connection or an explicit QMetaObject::invokeMethod, using the connection type QueuedConnection (which passes an event into the event loop of the thread of the object, so your file names are automagically queued by being contained in that internal slot call event).
If I'm using QObject->moveToThread(), that thread is then running in an event loop?
Those are completely unrelated. A bare QThread is running the event loop as soon as you start() it. For this to happen you don't need to move any objects to it. Of course the event loop is dormant since there are no incoming events for it to process - so the thread, in spite of having been started, doesn't consume any CPU.
The thread (event loop) is tied to QObject's signals and slots, right?
Signals and slots are simply function call sources and sinks that you can link up. They have not much to do with event loops.
When the sender and receiver objects reside in different threads, the delivery of a slot call is implemented by posting a QMetaCallEvent to the object's event queue. That even, like all events, is given to QObject::event(QEvent*) method. That method acts on the QMetaCallEvent and executes the slot call.
So I need to then have this Object's scope be the calling thread by putting it in the constructor? (And quit() wait() in the destructor) It therefore runs for the entire lifetime of the original thread?
The object's lifetime is decoupled from thread's lifetime. An object that is moved to a given thread can only be destructed from that thread. If the thread terminates first, the object becomes threadless (its thread() returns nullptr), and it can be destructed from any thread, or moved to another thread. A threadless object can't receive any events, but of course it can receive direct slot calls. Queued slot calls won't work since those are delivered as events initially, and only internally converted into calls.
I don't think I need to have a slot for the QThread, because I only want to invoke it, not communicate back and forth.
A QThread is a thread controller. There's very little reason to subclass it. In almost all cases you can either use a QObject that has been moved to the thread, or QtConcurrent::run.
So I would do something like this: [...] Create an instance of the QThread: [...] Send it the string.
You want to send the string to an object that lives in the thread, not to the thread itself.
Here's a small example:
// main.cpp
#include <QThread>
#include <QCoreApplication>
#include <QDebug>
class Worker : public QObject {
public:
Q_SLOT void say(const QString & str) { qDebug() << str; }
};
/// A thread that's safe to destruct at any time.
class Thread : public QThred {
using QThread::run;
public:
~QThread() { quit(); wait(); }
};
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
Worker worker;
Thread thread;
thread.start();
worker.moveToThread(&thread);
// Equivalent to invoking the say slot from a signal
QMetaObject::invokeMethod(&worker, "say", Q_ARG(QString, "hello"));
//
QMetaObject::invokeMethod(&app, "quit");
return app.exec();
}
#include "main.moc"
It sounds like your thread is supposed to process a char* and then wait. If this is the case, there's a third option available to you where you have a single function that runs in a separate thread and then exits, using QtConcurrent::run()
Simple example:
void workerFunction(QString const &data){
// ...
}
void callingFunction(){
// ....
char *data = .....;
QFuture<void> future = QtConcurrent::run(workerFunction, QString(data));
}
EDIT:
If you need more features than a single threaded function but not as many as a fully-fledged subclass of QThread, there is also the QRunnable/QThreadPool pair as a convenient intermediate option.

QThread - how to stop worker?

I'm reading that I should use worker object and move it to thread by moveToThread instead of inherit from QThread directly. But I can't find solution how to stop loop in my object worker. For example I have test loop:
void CollectionWorker::doWork()
{
for (int i = 0; i < 10; ++i) {
sleep(1);
emit ping(i);
}
}
Now I'm moving this object to thread:
worker->moveToThread(mTh);
This is working fine. But when I call mTh.quit() then thread is waiting until loop in doWork is end. When I inherit from QThread directly then on each loop I can check thread status and break loop when thred is finished but don't know how to do it in worker object. Can I just create some flag in worker object and switch it from main thread? Or maybe can I find thread owner and check it status? Or maybe better before starting thread, set thread pointer in worker object and then check status? What is the best thread safe solution?
Regards
Calling quit() or exit() on a thread object will simply end the event loop of the thread if there is any running. But As you rightly pointed out, the original problem remains the same. What if the worker function has already been executed by event loop and is a long running function with forever construct. The call to quit() or exit() will simply wait till the worker function returns.
Couple of approaches can be suggested apart from making a public function available to caller which will alter an internal flag.
Give a termination signal and slot in your worker class. Something as following.
signals:
void signalTermination();
public slots:
void setTerminationFlag();
private:
QMutex mutex;
bool terminationRequested;
Your slot would look like something.
void setTerminationFlag()
{
QMutexLocker locker(&mutex);
terminationRequested = true;
}
Then you can check the variable in your doWork function in every iteration of forever loop.
mutex.lock();
if(terminationRequested)
{
//break from loop and effectively doWork function
}
mutex.unlock();
One of the reason of using signals and slots instead of plain member function is that, if your worker function is doing some long running task inside synchronized code block, the public function will remain blocked until it gets access of the synchronization object. This might have adverse effect if the calling thread of your public termination method is UI thread.
Another clean and simpler approach if you are using Qt 5.2 onwards
Use requestInterruption() method of QThread. This method sets an advisory flag in the thread object which you can check via isInterruptionRequested() function call in your doWork() function. See following code snippet given in QThread::isInterruptionRequested documentation.
void long_task() {
forever {
if ( QThread::currentThread()->isInterruptionRequested() ) {
return;
}
}
}
You can also directly call quit() here to end the event loop of the thread.
Edit: Sorry i've misunderstood your question.
There are several alternatives. You can create some flag and before each iteration of your processing loop you check if the flag has been set. Or, in the case your processing data in a list/queue maybe you could signal the process to terminate with a special end-of-data element.
I have the same problem as Dibo had. I'm running a long calculation loop inside my doWork() function and need to be able to stop it from my main thread.
Chadick Robbert's answers didn't do the trick for me. The first suggestion behaved just like what he describes for member functions. That is, although we're using signals and slots, calling setTerminationFlag slot from a signal emitted in the main thread, properly connected to it, only gets executed after the loop ends. But maybe I did something wrong with the implementation. If it really is supposed to work please let me know, because it seems like the deal breaker.
His second alternative of using QThread::currentThread()->isInterruptionRequested() to tell the thread to stop would work great if it weren't for the fact that you can't reset this flag if you plan on reusing the thread and worker for some similar processing intensive loop, if not the same. Surely you can get it done by stopping and starting the thread, but I'm not sure if it wouldn't have adverse effects like clearing execution queues on it. This issue was actually posted as a bug report and Thiago Macieira (key developer for Qt) mentions there, if I may quote him:
The purpose of the requestInterruption function is to finish the thread.
Which makes requestInterruption inadequate for the job, as it is reset only on thread start and finish.
A solution that I found, that doesn't seem all that clean to me, is to include QCoreApplication in the worker class and call QCoreApplicaton::processEvents() from time to time, to process those queued signals in Chadick Robbert's first suggestion or update the worker's class awareness of flag variables shared between threads.
Because calling QCoreApplicaton::processEvents() within your loop can slow it dramatically what I do is something like:
for(unsigned long int i=0; i<800000000 && !*stop; i++){
f += (double)i * .001; // dummy calculation
if(i%10000000 == 0) // Call it only from time to time
QCoreApplication::processEvents(); // update *stop according to main Thread
}
As you can see, with this solution the loop will only break at integer multiples of '10000000' which may not be adequate for some use cases.
If anyone knows of a killer solution to this I'd love to hear.
The idiomatic way in Qt to destroy a worker thread is using the signal/slot interface:
CollectionWorker *worker = new CollectionWorker;
QThread *workerThread = new QThread(this);
connect(workerThread, SIGNAL(started()), worker, SLOT(doWork()));
connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
worker->moveToThread(workerThread);
In order for this to work CollectionWorker must inherit from a QObject class and declare the Q_OBJECT macro.

Questions about implementing QThread in my application?

As suggested in this question, I am now trying to incorporate multithreading.
According to the links given by karlphillip, I understand that the documentation about subclassing QThread is not to be followed and to use moveToThread() as explained. Now I see that default implementation of QThread run() has only an exec() which must then be ended by calling quit() when worker thread has finished operations. I have a few questions now so that I understand things better:
QApplication* ptrApp=new QApplication(argc,argv);
QThread* th=new QThread;
MyClass* obj=new MyClass;
obj->moveToThread(th);
QObject::connect(th,SIGNAL(started()),obj,SLOT(someFunct()));
QObject::connect(obj,SIGNAL(over()),th,SLOT(quit()));
th->start();
//some GUI code in main thread here
return ptrApp->exec();
What happens if I continue to use someFunct() even after I emit over() from within someFunct()? Is it undefined behaviour or normal?
Which thread would obj now be associated with (while the rest of the code after emitting over() is still executing in someFunct)? My understanding is: it cannot be in th when I have quit() that thread... quit() will be queued until the exec() in the main thread executes it which will cause the exec() in run() of th to exit (I hope I am not making a mistake here). I assume that thread is no longer existent.
Once slot quit() for th is executed, is it safe to assume that the thread has indeed quit or should I further connect finished() signal of th to some slot to be absolutely sure?
It doesn't matter if the event loop is terminated, somefunct() will continue to run until it gives control back to the now extinct loop.
obj stays associated to the thread, so if a signal connected to one of its slots is emitted, the slot won't run but it will be queued for when/if the thread is restarted.
If the QThread object is deleted, obj->thread() returns 0, so I suppose this would be equivalent to calling obj->moveToThread(0) and according to the documentation:
If targetThread is zero, all event processing for this object and its children stops.
quit() terminates the event loop, then the finished() signal is emitted from the thread, and the thread terminates.
So, even when you receive the finished() signal, you shouldn't assume that the thread is finished yet. You can use QThread::wait from the main thread, after you receive that signal to ensure that.
If the thread is in the finishing state, the QThread destructor already calls wait, so you can safely delete the thread after the finished() signal (with deleteLater() to be even safer).
1. What happens if I continue to use someFunct() even after I emit over() from within someFunct()? Is it undefined behaviour or normal?
As you are using direct connections, emitting over will call directly the function quit, which stops the event loop and return from the exec in the thread run method. Which means someFunct() will not finish its execution and the objects inside it are either lost or in a partial modified state.
2. Which thread would obj now be associated with (while the rest of the code after emitting over() is still executing in someFunct)?
As said previously somefunct will not finish its execution. But I believe any objects associated with this thread will remain as such. I say I believe because there is no solid assertion anywhere, but it make sense the most. As mentioned in the doc, for these objects to send or receive events the thread must be started again....
3. Once slot quit() for th is executed, is it safe to assume that the thread has indeed quit or should I further connect finished() signal of th to some slot to be absolutely sure?
quit() terminates the event loop and return where exec() was called.
Notice that the object Qthread is not the thread. so until you enter exec(), it is the main thread which is running... As well as it is the main thread which runs after the exec.
Anyway these are some great questions...