QtCore dependence on QCoreApplication - qt

I am trying to use Qt as a library (similar to this), because I want to reuse Qt classes in some currently non-Qt applications, and in shared libraries as cross-platform glue. Everything is non-GUI.
Some problems are easily avoided by DirectConnection, some can be solved with private event loops, even one can run a fake QCoreApplication in a thread and it works (last resort).
I want to know what modules rely on a running instance of QCoreApplication and cannot work without it.
Some of the Qt modules (in QtCore) do need an instance of QCoreApplication to run properly. For example QTimer relies on QCoreApplication to dispatch timer events.
I was reading the documentation for QtConcurrentRun and it seems to be relying on a global instance of QThreadPool, I am about to try and see if the application execution is vital, or maybe the instance is created on first access, or maybe not.
I am going to study QCoreApplicationPrivate source (Windows and Linux for now) but any hints in the right direction is greatly appreciated.
What are other functionality dependencies to the core application? Note that it might depend on the OS.
Edit1: Thanks to Kuba's answer, It seems QCoreApplication event loop is not necessary for timer and socket events to be dispatched. So some QtCore modules require and instance of QCoreApplication, but there is no need to have a running application event loop.

You are conflating the existence of a QCoreApplication with a running event loop. Those two are separate concepts. You may well need the former for the latter, but the latter doesn't have to run in the same thread as the former.
Most notably, you don't really have to call qApp->exec() if you don't have any events to dispatch in the thread where you constructed QCoreApplication.
The existence of a QCoreApplication is, as it were, a non-issue. Things get hairier with QApplication -- you can start it in a non-gui thread, but it's not portable and won't work on OS X. I'm trying to figure out why it doesn't work, but I don't have much time now to offer a satisfactory solution -- not yet.
It is also a misconception that QCoreApplication's event loop needs to be running for socket notifications and timer events to be dispatched to other threads. A QCoreApplication's event loop is nothing special. There is a platform-specific instance of QAbstractEventDispatcher that gets created for a thread when you instantiate the first QEventLoop in that thread. The QEventLoop doesn't know anything specific about the platform.
QCoreApplication's exec() method is quite simple and creates an instance of QEventLoop, and thus will create an instance of platform-specific QAbstractEventDispatcher. This instance is not special in any way. It's the same as any other event dispatcher created in any other thread, as far as my code reading tells so far.
If all underlying window systems would support it, it'd be in fact possible to make Qt GUI code multithreaded -- the per-thread event reception and dispatch is already there as a small first step. The big obstacle, probably the only one, would be the X library and its display lock. The display lock would be an obvious matter of contention between threads. You'd need each thread that wants to talk to the GUI open up a separate connection to the X server, and I don't know if there's a supported way of doing that from Xlib.

Related

Qt: Multi-Threaded DLL Design

Intro
This is an open ended question that I thought could be beneficial to the community because I have been unable to find great documentaton in regards to this. Unfortunately, I learned the hard way that implementing a DLL in Qt is different than in other languages as I will explain later
Problem Statement
Implement a multithreaded DLL in Qt that can easily be used by non-Qt applications
Background Info
Qt is the tool of choice because its inherent cross-platform compatibility
The API makes use of callback functions to tell the calling application when certain events have occurred
Assumptions
-The applications that will link to the Qt dll are compatible with Qt compilers (c/c++ -mingw, C# -msvc)
-Signals/slots are used to communicate from main thread to worker threads (e.g. tell a worker thread to collect data) as well as from worker threads back to main threads (e.g. notify the main thread via a callback function that data collection has completed)
Problem Description
I learned the hard way that writing a multi-threaded DLL in QT is different than other languages because of Qt's architecture. Problems arise due to QT event loops that handle spwaning threads, timers, sending signals, and receiving slots. This Qt even loop (QApplication.exec()) can be called from the main application when the main app is Qt (Qt has access to QT specific libraries). However, when the calling application is not Qt, C# for example, the calling application (aka the main thread) does not have the ability to call Qt specific libraries therefore, making it necessary to design your DLL with an event loop embedded inside of it. It is important that this is considered upfront in the design because it is difficult to shoe-horn it in later because QApplication.exec is blocking.
In a nutshell, I am looking for oppinions on the best way to architect a multithreaded dll in Qt such that it is compatible w/ non-QT applications.
In Summary
Where does the event loop reside in the overall architecture?
What special considerations should you make in regards to signals/slots?
Are there any gotchas that the community has come across when
implementing something similar to what I have described?
[...] when the calling application is not Qt, C# for example, the calling application (aka the main thread) does not have the ability to call Qt specific libraries therefore, making it necessary to design your DLL with an event loop embedded inside of it.
This is not accurate. On Windows, you need one event loop per thread, and that event loop can be implemented using pure WINAPI, or using C#, or whatever language/framework you need. As long as that event loop is dispatching windows messages, Qt code will work.
The only Qt specific thing that needs to exist is an instance of QApplication (or QGuiApplication or QCoreApplication, depending on your needs) created from the main thread.
You must not call exec() on that instance, since native code (the main application) is already pumping windows messages. You do need to call QCoreApplication::processEvents once after you create the application instance, to "prime" it. That you do need to do so is a bug (omission) and I'm not sure that it's even necessary in Qt 5.5.
Afterwards, the gui thread in the native application will properly dispatch native events to Qt widgets and objects.
Any worker threads you create using unaltered QThread::run will spin native event loops and each of these threads can host native objects (windows handles) and QObjects alike, as well as execute asynchronous procedure calls.
The simplest way of setting it all up is to provide an initialize function in the DLL that is called by the main application once to get Qt going:
static int argc = 1;
static char arg0[] = "";
static char * argv[] = { arg0, nullptr };
Q_GLOBAL_STATIC_WITH_ARGS(QApplication, app, (arc, argv))
extern "C" __declspec(dllexport) void initialize() {
app->processEvents(); // prime the application instance
new MyWindow(app)->show();
}
The requirement for initialization not to be done in DllMain is not specific to Qt. Native WINAPI-using code is forbidden from doing mostly anything in DllMain - it's not possible to create windows, etc.
I reiterate that it's an error to do anything that could be allocating memory, window handles, threads, etc. from DllMain. You can only call kernel32 APIs, with some exceptions. Allocating a QThread or QApplication instance there is an obvious no-no. Queuing the APC call from a "current" (random) thread is the best you can do, and there's still not a firm guarantee that the thread will survive long enough to execute your APC, or that it will ever alertably wait so that the APCs can get a chance to run.
If you're feeling adventurous, according to this answer, you could queue the call to initialize() as an APC. The major problem then is that you can't ever be sure that DllMain is called from the right thread. The thread it's called from must end up in alertable wait state (say pumping the message loop). You can create a dedicated application thread then, and it's not possible to figure out if there is any particular other "main" thread that should be used instead of the new one. The thread handle must be detached, thus we must use std::thread instead of QThread.
void guiWorker() {
int argc = 1;
const char dummy[] = "";
char * argv[] = { const_cast<char*>(dummy), 0 };
QApplication app(argc, argv);
QLabel label("Hello, World!");
label.show();
app.exec();
}
VOID CALLBACK Start(_In_ ULONG_PTR) {
std::thread thread { guiWorker };
thread.detach();
}
BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
{
switch (reason) {
case DLL_PROCESS_ATTACH:
QueueUserAPC(Start, GetCurrentThread(), NULL);
break;
case DLL_PROCESS_DETACH:
// Reasonably safe, doesn't allocate
if (QCoreApplication::instance()) QCoreApplication::instance()->quit();
break;
}
}
Generally speaking, you should never need such code. The main application must call the initialization function from a thread with an event pump (usually the main thread), and everything will work then - just as it would were it initializing a DLL using native functionality only.
Just to provide a quick update on this so you can learn from our mistake. We ran into all types of problems when we tried to integrate our Qt written dll with non-Qt languages such as C# because of the issues listed above. While Qt is great at providing a multi-platform solution it has the drawback of not being very DLL friendly as it is very difficult to get the DLL working any language other than Qt. We are currently investigating whether or not we want to rewrite our entire DLL in standard portable C++ and scrap the Qt implementation which would be very expensive.
Fair warning, I would avoid using QT as your framework when creating DLLs.

How QEventLoop must be used when we don't subclass QThread in Qt 4.8x?

I've read there are two approaches for working with QThread.
If I have a Worker class, which inherits QObject (as in http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/), then how should I create and manage local QEventLoop for working with signals/slots? I don't want to have memory leaks.
How QNetworkAccessManager should be created in worker described in http://codethis.wordpress.com/2011/04/04/using-qthread-without-subclassing/?
If you don't subclass QThread, it has its own event loop (Fixed QThread documentation of Qt 5, also appliccable for Qt 4):
By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.
Managing the work done by the worker can be easily done using signals & slots:
(...) you are free to connect the Worker's slots to any signal, from any object, in any thread. It is safe to connect signals and slots across different threads, thanks to a mechanism called queued connections.
This means you usually don't need to care about any event loop on your own (unless you require special behaviour). Simply connect the thread's started signal to any slot of your worker object and make sure you set up some kind of deletion chain: Either the worker emits a signal which leads to the thread being stopped and deleted, or the other way round - both ways work, depending on your situation.

QObject destructors not being called

I have two QObject child classes in my Qt application. One object from each of these classes was instantiated on the stack. Previously, my application would exit cleanly. However, since I've updated to Qt5.1.0, their destructors are not being called. I get the following warning twice when I launch the debugger.
the debug information found in "/usr/lib/debug//lib64/libfreebl3.so.debug"
does not match "/lib64/libfreebl3.so" (CRC mismatch)
Is this a bug in Qt or in my code?
See the documentation of QCoreApplication::exec:
We recommend that you connect clean-up code to the aboutToQuit() signal, instead of putting it in your application's main() function because on some platforms the QCoreApplication::exec() call may not return. For example, on Windows when the user logs off, the system terminates the process after Qt closes all top-level windows. Hence, there is no guarantee that the application will have time to exit its event loop and execute code at the end of the main() function after the QCoreApplication::exec() call.
You're using it incorrectly. It is not guaranteed that exec will be terminated after windows are closed. You should use aboutToQuit signal to stop other threads. If this signal is not emitted either, you need to call QApplication::quit() explicitly when your window is closed.
I'm not exactly sure in this case if this is a bug in your code or not, but anyway it is not recommended to create QObjects in the stack.
The reason is that the parent object (if any) will automatically call delete when destroyed, but then the object will also be automatically destroyed when it goes out of scope. Hence the object is destroyed twice which is Undefined Behaviour. That may explained why it worked well in one case, and not in another, since you can't rely on any consistent behaviour.
(But in your case it is weird that you say the destructor is not called at all...)

Using QFtp in a console app

I'm an advanced beginner using Qt and I'm trying to write a console app that uses QFtp. The app itself is essentially just procedural code but because QFtp is asynchronous this is driving me crazy. I need to test that multiple ftp downloads are successful, but the code doesn't block so the test always fails. The best solution so far is to create a chain of signals and slots daisy chaining the ftp code and the procedural sections. It seems there has to be a better way. Any ideas?
You can use QEventLoop to wait for a signal. Just connnect the signal to QEventLoop::quit(), and then call QEventLoop::exec().
QFtp ftp;
QEventLoop eventLoop;
connect(&ftp, SIGNAL(commandFinished(int,bool)), &eventLoop, SLOT(quit()));
eventLoop.exec();
As it's asynchronous you're best off tracking it through the signal and slots mechanism, but that does throw off your procedural logic. The only other default option for FTP in Qt is QNetworkAccessManager but that's also asynchronous, so whichever you go for you're going to have to use the signal/slots system to track when it's done.
You could use QTcpSocket and write your own FTP code, that allows you to block the calling thread until it returns with certain conditions, but you'll have to write significantly more code to do what you want to.

Qt 4.7 Emitting a signal to a specific thread

I have several client GUI windows all derived from QMainWindow. Each window is potentially doing a different task but all are requesting data from a central cache implemented as a QThread.
All the clients connect to the same slot in the data cache and then emit signals to prompt the data cache to do something. The signals to the data cache get queued so the data cache only ever does one thing at a time.
When the data cache completes it needs to inform the correct client that the thing it was doing has completed. My immediate thought is to emit a signal to the requesting client about the completion. This would mean connecting to a specific client's slot and then emitting a signal to it.
Do I have to do connect and then disconnect to the client? I'm aware of the QObject::sender() function to get the supplier. Is there some way of emitting a signal to that sender (client) only? Or is there some other way of doing this?
There may be simpler approaches you can take to resolve your problem. For example, I would consider looking into the QtConcurrent framework. Alternately, you might also re-architect your design such that the client first connects to a "finished" signal on the cache prior to asking the cache to do anything. Failing all of that, you might also consider relying on the QMetaObject::invokeMethod function (for either your client or your cache). This function allows you to call an arbitrary method on an arbitrary QObject (provided that you have a pointer to it) using arbitrary generic arguments (in a way that's thread-safe).
If you use the QMetaObject::invokeMethod approach, there are a few of drawbacks you should be aware of. Firstly, you have to invoke the method using its string name, which means that you won't find out at compile time if you're using the wrong name. Secondly, since your clients have a different thread affinity than the central cache, there's a chance that the client will have been destroyed when the cache invokes the method on them (though perhaps in your case, this won't be a problem for you). Finally, you may not want your cache to have any knowledge of the names of the methods that it must execute on its client.
I don't have any way of getting around the first drawback (I'm not sure if this is going to be handled differently in the upcoming Qt 5.0 release). As far as the second and third problems, I would recommend creating an object that encapsulates a reference to a method -- something like the following:
class MethodReference
{
MethodReference(QObject* object, const QString& methodName);
...
bool invoke(QGenericArgument val0 = QGenericArgument(),
QGenericArgument val1 = QGenericArgument(),
...
QGenericArgument val9 = QGenericArgument());
private:
QPointer<QObject> mObject;
QString mMethod;
};
You would then pass this object to your cache from the client. The cache then calls invoke on this object.
Note the use of QPointer -- this gives you a thread-safe way of checking if your object has been destroyed before you try to invoke a method on it. Since I've done this before, I'll also let you know that versions of Qt prior to 4.8 had a bug in QPointer that would cause a crash in a multi-threaded context. Use a more recent version of Qt if you want to do this.
I hope this was clear.

Resources