I'm trying to determine how calling QObject slots or Q_INVOKABLE methods from QML for a QObject that lives in another thread works, and whether or not its safe to do so.
Assume there's a MainThread and ThreadA. QObjectA lives in ThreadA. The QML engine/gui/everything lives in the MainThread. I expose QObjectA to the QML engine using
declarativeView->setContextProperty("someObj",ObjectA)
Now in a QML file, I call
someObj.someMethod();
Where someMethod is a slot or is Q_INVOKABLE. I'd like to know which thread actually executes the function. If it's MainThread, that would be a bad thing, and calling a method like that across threads would be dangerous. If it was executed by ThreadA however, all would be well.
Based on this documentation: http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html, I'm assuming that QMetaObject::invokeMethod() is used to call the QObject function. That documentation (http://doc.qt.nokia.com/4.7-snapshot/qmetaobject.html#invokeMethod), shows that there are different connection types available, just like with Qt signals and slots.
I'd like to know if Qt's qml engine automagically chooses the right type for the situation when invoking C++ methods from QML across threads, and if so, calling methods for objects that live in other threads from QML is an acceptable practice.
As it became apparent a while ago, QML doesn't seem to be able to go across threads.
So one needs to implement a C++ side intermediate object that lives in the main thread to dispatch calls to objects in other threads.
QML object -> object in a different thread // doesn't work!!!
QML object -> C++ mediator object -> object in a different thread // WORKS!!!
Basically, "transcending" threads must happen in C++ entirely, thus the need of a mediator object.
I guess the someMethod will be executed in ThreadA since the object lives in that thread.
But normally if this gives a problem, then I would do something like this.
connect(&threadA, SIGNAL(started()), someObj, SLOT(someMethod());
But to start that ThreadA we need one more CppObject to link QML and CPP.
You can use this->thread(); or QThread::currentThreadId(); inside the slot to get the thread the slot is working in. It will always be the thread, the ObjectA was created in (if there was no moveToThread()).
The Qt-Engine will select the right Qt:ConnectionType by determine call and called thread.
Extra tip: You can use GammaRay or ThreadSanitizer to see current direct connections across threads.
QML logic is event-driven and all invokes are parts of JavaScript functions. JS functions may be event handlers (for ex. UI event handlers) or may be invoked somewhere in C++ code if you wrap them in QScript object. Also you can invoke them in JavaScript WorkerTherad. That is why only you can provide an answer, where does someObj.someMethod() invokation take place.
Related
I have this call stack to perform a heavy computation:
// QML
StyledButton {
onButtonClicked: {
registeredCppClass.undoHandler.createCommand()
}
}
void UndoHandler::createCommand()
{
m_undoStack->push(new Command());
}
class Command : public QUndoCommand
{
public:
Command();
virtual ~Command();
virtual void undo();
virtual void redo();
// ...
private:
// Handler does the logic
LogicHandler *m_logicHandler;
// Output by logic handler
QString m_outputName;
};
void Command::redo()
{
if (/* */) {
} else {
// Run heavy computation
m_outputName = m_logicHandler->run();
}
}
QString LogicHandler::run()
{
// Heavy computation starts
}
Intention
I intend to implement QThread by this approach to prevent GUI from getting non-responsive while heavy computation is being done. But I don't know where QThread and Worker class need to be implemented. Should they be within:
UndoHandler::createCommand
Command::redo
LogicHandler::run
... ?
What is the best location for QThread and Worker considering their signal-slot connections?
The general advice is to never read QThread documentation. Follow that up with never read Linux thread documentation. I say this as someone who has written quite a few books on software development.
The long answer is threading wasn't well thought out early on and there is a lot of, now bad, information out there. During Qt 3.x and I believe early Qt 4.x one was supposed to derive a class from QThread and override the run(). You can imagine just how well that worked for newbie developers unfamiliar with threads in general and unable to design in mutex or other access protection when manipulating things in multiple threads.
Your design makes it appear you have read some of this documentation. It's still floating around out there.
At some point during Qt 4.x we were no longer supposed to derive from QThread. Instead we were supposed to just create a QThread and moveToThread(). Kinda sorta worked but you could still end up with "dangling threads" if your program didn't follow the happy path through the code.
Around the same time, at least as far as my exposure, we also got a global thread pool.
Your design is really flawed because you looked at old doc. Not your fault. The old doc tends to turn up first in searches.
Visit this GitHub repo and pull down the project. The only dev_doc setup documentation I have completed is for Fedora. I will be working on Ubuntu this morning if I don't get interrupted. Be sure to check out the diamond-themes branch.
Yes, this is using CopperSpice, but CopperSpice is a fork of Qt 4.8 and this is the only concrete code example I could think of off the top of my head. You can build and run the editor or you can poke-and-hope by reading advfind_busy.cpp. What you are looking for is how QFuture is used. That source file is only about 200 lines long and it has a short header file.
Throw out your current design. You need QFuture and QtConcurrent::run().
Note: The header files for these things are different in name and location when compared to current Qt 5.x. That much you will need to look up if you choose to stay with Qt. How you use this stuff is not.
Note 2: If you don't have some kind of throttle control to limit each of these tasks to a single thread instance you will need to dynamically create and destroy QFuture objects. This means you have to have some kind of list or vector keeping track of them and your object destructor needs to walk that list killing off the threads and deleting the objects.
If you want to go on a journey setting up CopperSpice on Ubuntu it is spread across a multi-part blog post starting here.
IMHO, your intentions are correct, and you are headed in the right direction (leaving aside the argument for using QtConcurrency -- thread pools and futures -- since that's not pertinent to the immediate question). Let's address the first part: the objects and execution flow.
As the classes have been outlined in the code snippets, you will need to take extra care to correctly push them across thread boundaries. If you think for a moment, the worker object is created in the calling thread, therefore some of the object's members will also be created in the calling thread. For members which are pointers, this does not pose much of a problem, because you may elect to delay the creation of those objects until after the enclosing object instance has been created and moved to the worker thread. But, embedded objects are created when the object is constructed. If the embedded object derives from QObject, it will have its thread affinity set to the caller thread. In such a case, signals won't work properly. To alleviate this problem, it is often easiest to pass the work thread to the worker object's constructor, so the worker object is able to move all of its embedded objects to the worker thread.
Second, assuming the following:
Command holds a unique instance of LogicHandler, and
LogicHandler does not have state, and
LogicHandler is a subclass of QObject, and
LogicHandler is the worker class
My advice would be to place the spinning up of the thread in Command::redo, then connect the signals similar to advice given at the bottom of this article. Also, you would not set Command.m_outputName to the return value of LogicHandler::run. LogicHandler::run should return void. Instead, you should add a signal to LogicHandler that emits the string value when it has finished processing; then, add a slot in Command to handle that. A QString can easily be marshaled across thread boundaries (make sure you make the connections of the proper type, see here).
The connecting of the worker startup method, to the threads started signal gets the execution started. There is no need to inherit from QThread and override run. The worker should also emit a finished signal, that should be connected to the thread's quit slot. The worker's finished signal should also be connected to both the thread's and worker's deleteLater slot. When these are setup, just call the thread's start method.
From there, the execution will return from redo, and you will be notified that the worker is finished when it emits a signal (the one I mentioned that you will need to add) and passes the output string. If the lifetime of the worker is different (I'm guessing longer, since you need to spin up a thread to do long operation) from the instance of Command, then you will need to connected the return value signal from the worker object to a different object.
I'm using threaded application written in Qt (C++).
I need to make get/post request very often from separate threads.
Qt doc says:
One QNetworkAccessManager instance should be enough for the whole Qt
application. Since QNetworkAccessManager is based on QObject, it can
only be used from the thread it belongs to.
Is static thread_local QNetworkAccessManager good choice for my purpose?
No, not a good choice.
You shouldn't create static or global QObject subclass instances, because you generally need them to be created after the Qt application object has been created (a lot of Qt stuff depends on the application object existing already). C++ does not really provide very good control over when static objects are actually created, and here you want to have that control.
Just use a pointer and new to create the QNetworkAccessManager instance, as many of them as you want. You could create them in the right thread directly, or you could create them in some other (usually main) thread and move them to the right thread.
To get them destroyed properly, when they don't have a natural parent (because the parent must live in the same thread!), connect the their thread's QThread::finished signal to the objects QObject::deleteLater slot, and they will get cleanly deleted when the thread finishes.
If you want a plain function, which uses the current thread's QNAM instance, you could have thread-local static pointer. Something like
static thread_local *thread_qnam;
void myfunc() {
if (!thread_qnam) {
thread_qnam = new QNetworkAccessManager;
connect(QThread::currentThread, &QThread::finished(), thread_qnam, &QObject::deleteLater);
// Whatever other setup you need.
// It'd probably be good idea to wrap this in a function.
}
// Use thread_qnam...
}
I'm learning Qt and I'm having lots of fun with the signals-slotpattern. The question that I have is that, are signals and slots simply syntactic sugar for event listeners and handlers or what happens in the background is of different nature? If the later, what is the fundamental difference?
This is not just syntactic sugar. There is a real work in the background of Qt signals/slots. This work is done by the MOC (Meta-Object Compiler). This is the reason there is a process on all of your C++ header files that contains class with Q_OBJECT macros.
The "hard part" of signals/slots is when you are in a multithreading context. Indeed, the Qt::ConnectionType argument of connect() function, which is Direct (e.g. direct call of the function) in a single-threaded environment, is Queued in a if sender and emitter aren't in the same thread. In this case, the signal must be handled by the Qt event loop.
For more details: http://qt-project.org/doc/qt-4.8/signalsandslots.html
Are signals and slots syntactic sugar or there is more to them? The question that I have is that, are signals and slots simply syntactic sugar for event listeners/handlers
No, the mean reason for their existence is decoupling of the emission and handling.
or what happens in the background is of different nature?
The idea is that you separate the emission from the handling of a certain "event". If you consider the direct function calls as an alternative, I would like to point that out, with them, the code responible for the emission would need to be aware of the code that actually handles the "signal". That is the two parts would be too tight too each other.
It would not be possible to dynamically add another handler for the signal without changing the code that is responsible for the signal emission. Imagine an example like this:
Some part of the code emits a signal "fruit arrived"
This code would directly call the "wash fruit" method.
What if someone would like to add a method to count the number of fruits?
The previous code would need to be modified to include the direct call to that method.
With the signal-slot mechanism, you would not need to touch the original code. You could just simple connect your new slot to the existing signal from an entirely different piece of code. This is called good design and freedom.
This is especially useful when you have libraries like Qt that can emit signals all around without knowing about the Qt applications in advance. It is up to the Qt applications how to handle the signals, on their own.
In addition, this pattern also makes the application more responsive and less blocking, which would be the case with direction function calls. This is because of the existence of the event loop on which the Qt signal-slot mechanism is built upon. Surely, you could use threading with direct calls, too, but it becomes a lot more work and difficult to maintain than it would be necessary in an ideal world.
So, as partially already touched, there is a QtEventLoop in the background queuing up these events for processing, although it is possible to execute "direct calls", too.
The really background internal implementation code can be found there, and in moc (meta object compiler). Moc is basically creating a function for signals which you do not define a body for, so you just declare them in the QObject subclasses when you need it.
You can read more upon the topic in here, but I think my explanation could get you going:
Qt Signals & Slots
QtDD13 - Olivier Goffart - Signals and Slots in Qt 5
How Qt Signals and Slots Work
How Qt Signals and Slots Work - Part 2 - Qt5 New Syntax
Signals and Slots in Qt5
Using the Meta-Object Compiler (moc)
The signals and slots are a way to decouple the method call from the called method. They are not syntactic sugar at all since they add no new syntax to the C++ language. A signal emission is a method call. A slot is a plain old instance method. The code that links the two is plain old C++. Nothing new here - no sugar of any kind.
Most of what you call "the syntactic sugar" is akin to comments - those are empty defines (Q_SLOT, Q_SIGNAL, signals, slots) used to mark the methods for processing by the meta object compiler (moc). Moc generates introspection information and signal implementations based on normal C++ syntax of the declarations (with some limitations).
I claim that this is not syntactic sugar since moc understands regular C++ and generates introspection data based not on any syntactic sugar, but on usual instance method declarations. The "sugar" is there to avoid the premature pessimization of having moc generate metadata for everything in a class's declaration. It also lets moc ignore the method definitions - otherwise it'd need to parse them, and assume that methods without definitions are signals.
The emit macro is only for human consumption and is merely an indication that a method call is really a signal emission. It's not used by moc. It's defined to be empty.
The Q_OBJECT and Q_GADGET macros declare some class members used to access the metadata. They are, arguably, the only piece of real "sugar" since it saves you from having to type out a few lines of declarations.
There's quite a bit of code potentially involved in making it work.
A signal:
is an instance method whose implementation is generated by moc,
has full introspection information about its name and arguments. This is available as an instance of QMetaMethod.
A slot:
is an instance method whose implementation you provide,
similarly has full introspection information.
The metainformation is available at runtime and can be enumerated and used by code that has no prior knowledge of the signal's nor slot's signature.
When you emit a signal, you simply call the method generated by moc. This method invokes Qt library code that acquires relevant mutexes, iterates the list of attached slots, and executes the calls, acquiring additional mutexes as needed along the way. Doing this properly requires care, since the sender and receiver objects can reside in different threads. One has to avoid delivery of slot calls to non-existent objects. Oh, you don't want deadlocks either. This requires some forethought.
Since both signals and slots are just methods, you can certainly connect signals to other signals - the underlying mechanism doesn't care what gets called, it's just an invokable method. Non-invokable methods are those without metadata.
A slot gets invoked when the relevant signal is emitted. A signal emission is just a method call to the generated body of the signal. This is different from event-listener pattern, since the slot invocation can be either immediate (so-called direct connection) or deferred to the event loop (so-called queued connection). A queued slot call is implemented by copying the arguments and bundling them in a QMetaCallEvent. This event is "converted" back into a method call by QObject::event. This happens when the event loop delivers the event to the target object.
The metadata contains more than just signal and slot signatures. It also allows you to default- and copy-construct signal/slot parameter types - this is necessary to implement the queued calls. It also contains key-value pairs for enumerations - that's what makes Qt rather easy to script. All enum values passed to Qt methods can be looked up by name, at runtime!
I'm wrapping libcommuni, which uses Qt, in a different DLL project, which doesn’t use Qt. As far as I’ve been able to tell, I need to run the Qt message pump (via QCoreApplication) to make sure networking, signals, etc. work properly. However, I’m running in to some problems figuring out how to do just that.
Basically, I want to spin up a thread in the DLL, which calls QCoreApplication::exec() and pumps all the Qt events. I then want to marshal external calls to the DLL, which are on a different thread, to the Qt main thread, so I can safely use libcommuni.
It looks like the recommended approach is to use signals and slots for this, but I’ve been unable to get that to work. I create a signal on the QObject class that is called via the DLL and I connect it to a slot on the QThread that runs the Qt message pump. However, if I specify Qt::QueuedConnection when connecting the signal and slot, the message is never delivered when I emit the signal. If I omit Qt::QueuedConnection altogether, the slot is called immediately on the calling thread rather than the Qt main thread.
I’ve also tried explicitly calling QCoreApplication::postEvent() on the DLL thread to send an event to the Qt main thread, but event(QEvent) is never called in the target QThread.
Any ideas on what I’m doing wrong here? I'm guessing I'm not quite understanding Qt's threading model.
When you use QObject::connect without specifying connection type - it uses Qt::AutoConnection, which turns into Qt::DirectConnection if the signal and slot are in a single thread, or into Qt::QueuedConnection, if they are in different threads. So, in your case, I can say, that for the moment, when you connect your signal with your slot, the objects, they belong to, are located in one thread.
In order to make Qt::QueuedConnection work, you need an event loop in a thread, which contains slot.
There are two main ways of using QThread:
You can derive QThread and rewrite QThread::run. In that case you should do several things:
When creating your thread's object, do not specify parent; remove this object manually.
In your thread's constructor call moveToThread(this).
In your thread's run method call exec after all initialization, but before all removal; thread will leave exec right after you call QThread::quit.
You can derive QObject, create QThread object, and call QThread::moveToThread on your object (which, by the way, should be created without specifying parent) before calling QThread::start.
In your case I would recommend using the second method.
That is about threads, but I am not quite sure, your problem isn't connected with QCoreApplication::exec.
So if I understand correctly, If I have a class FunctionsClassthat inherits QObject and i set that class up on a Qthread called FunctionClassThreadby doing:
FunctionsClass classObj;
classObj.moveToThread( &FunctionClassThread );
FunctionClassThread.start();
From what I understand this method of setting up a thread will only handle the execution of slots in the FunctionsClass, which means the thread running FunctionsClass can be blocked if a slot in FunctionsClass for some reason has a infinite loop.
So my questions are: How can I run the functions of FunctionsClass on a thread not just the slots? Is there a way to place a whole object (functions, member variables, etc) on a thread for execution of code/data from that whole object only? And is my understanding of how the thread will handle the execution of slots correct?
When you execute a method of an object it is executed in the thread you're invoking the method. It doesn't matter where the QObject is living.
If you want to invoke a method so that it is executed in another thread asynchronously you'll have to handle the situation so that the message is posted, waits for the thread to be available (might be busy, it has to return control to the event loop first) and then, run the method.
This can be done using signals and slots, with the usual connection. If you don't want to use that mechanism, you can use QMetaObject, but you still have to declare those as slots. The static method invokeMethod, if called with Qt::QueuedConnection will invoke the method in the thread in which the object owning the method is living. You can also pass arguments to the method and returns values from it.
Consider that any data types you want to be able to pass from a thread to another need to be registered with qRegisterMetaType and must respect the conditions reported in there.
Methods of a class will execute in the context of the thread that calls them. If you move a QObject class to a thread (let's refer to it as worker thread), then only methods of that class that are called directly (or indirectly) from the run() method of the worker thread, will execute in the context of the worker thread.
If you want to call methods on that class from some other thread, but still have them run in the context of the worker thread, then you need some way to get a message to the worker thread so it can call the method you want. This is essentially what is achieved by Qt signals and slots when thread boundaries are crossed.
With a lot of extra work, there are two other ways you can do the same thing. First, QThreads have an event loop which is started by default if you don't override run(). You can create custom events that you can post to the event loop which can trigger activity in your class that will execute in the context of the worker thread.
The second way would be to call methods in your class from another thread that modify class fields that the worker thread monitors. You need to be sure that access to any of these fields is synchronized with some mechanism like a mutex.