Is there a clean way to check on the current size of Qt's main application queue? Since I'm emit'ing quite a bit of signals, I'd like to monitor how big of a delay there is in processing the slot's on the Ui thread.
For example, after:
emit Signal();
emit Signal();
emit Signal();
I'd expect to be able to call something like this, which would tell me how many of those Signals are still left to process.
QApplication::checkQueueSize();
Just to followup, I've decided to go with a solution that instead will allow me to measure the latency through the queue. As multiple people pointed out, there is no real use-case for looking at queue size.
I've implemented this by mapping a timestamp from before "emit Signal" to after the slot gets called.
Imo, it should be possible (if only for logging/tracing purposes) to get information about a QThread's event queue size.
It's possible to get the size of the postEventList for a particular thread using the following snippet:
#include <QThread>
#include <private/qthread_p.h>
int getEventQueueSize(QThread* thread)
{
auto threadData = QThreadData::get2(thread);
QMutexLocker locker(&threadData->postEventList.mutex);
return threadData->postEventList.size();
}
You need to take special care w.r.t. the used include paths, because the paths to private/qthread_p.h and private/qobject_p.h need to be provided. So in addition to the usual includes, you need to add:
g++ ... -isystem /usr/include/qt5/QtCore/5.7.1/QtCore ...
Disclaimer: Use at your own risk. Since this touches the internals of Qt, and is probably unintended use, take extra care when using this. There may be a chance for a deadlock when the postEventList.mutex is locked (as in the above example). Also note that QVector is not threadsafe (postEventList is a QVector) and postEventList.mutex is non-recursive.
You probably already know that there's the QApplication::hasPendingEvents() from QAbstractEventDispatcher.
This is for Qt4, but after taking a quick look at the Qt5 source it looks like it's still not available:
How to intercept ALL signals emitted by a given event in QT?
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've faced quite an odd problem with QtConcurrent, mostly because of strange programming desires, maybe it's just an XY-problem, but...
So, there is my code, trying to communicate with the database, a backend code actually (on Qt, yes). It has to work quick and handle some requests, so I need a thread pool. As a well-known fact I suppose the connection establishing itself is a very time-consuming operation, so there is a need in persistent database connections resulting in persistent threads (QSqlDatabase cannot be moved around between the threads). Also it is quite natural to want asynchronous request handling, thus resulting in some need of a simple way to pass them to the persistent threads.
Nothing too complex, lets assume there already exists some boilerplate in a form like...
// That's what I want for now
QFuture<int> res = workers[i]->async(param1, param2);
// OR
// That's what I DO NOT want to get
workers[i]->async(param1, param2, [](QFuture<int> res) { // QFuture to pass exceptions
// callback here
});
That can be done for sure. Why not std::future? Well, it is much easier to use QFutureWatcher and it's signals for notifications about result's readiness. Pure C++ notification solutions are muuuch more complex and callbacks are also someting that has to be dragged through the class hierarchy. Each worker interfaces a thread with DB connections, obviously.
Okay, all of that can be written, but... custom thread pool would mean no QtConcurrent convenience, there seem to be only risky ways to create that QFuture so that it could be returned by the custom worker. QThreadPool is of no use, because it would be a whole big story to create persistent runnables in it. More to say, the boilerplate I've briefly described is gonna be some kind of project's core, used in many places, not something to be easily replaced by a 100 hand-made thread managings.
In short: if I could construst a QFuture for my results, the problem would be solved.
Could anyone point me to a solution or a workaround? Would be grateful for any bright ideas.
UPD:
#VladimirBershov offered a good modern solution which implements observer pattern. After some googling I've found a QPromise library. Of course, constructing a custom QFuture is still hacky and can be only done via undocumented QFutureInterface class, but still some "promise-like" solution makes asynchronous calls neater by far as I can judge.
You can use AsyncFuture library as a custom QFuture creation tool or ideas source:
AsyncFuture - Use QFuture like a Promise object
QFuture is used together with QtConcurrent to represent the result of
an asynchronous computation. It is a powerful component for
multi-thread programming. But its usage is limited to the result of
threads, it doesn't work with the asynchronous signal emitted by
QObject. And it is a bit trouble to setup the listener function via
QFutureWatcher.
AsyncFuture is designed to enhance the function to offer a better way
to use it for asynchronous programming. It provides a Promise object
like interface. This project is inspired by AsynQt and RxCpp.
Features:
Convert a signal from QObject into a QFuture object
Combine multiple futures with different type into a single future object
Use Future like a Promise object
Chainable Callback - Advanced multi-threading programming model
Convert a signal from QObject into a QFuture object:
#include "asyncfuture.h"
using namespace AsyncFuture;
// Convert a signal from QObject into a QFuture object
QFuture<void> future = observe(timer, &QTimer::timeout).future();
/* Listen from the future without using QFutureWatcher<T>*/
observe(future).subscribe([]() {
// onCompleted. It is invoked when the observed future is finished successfully
qDebug() << "onCompleted";
},[]() {
// onCanceled
qDebug() << "onCancel";
});
My idea is to use thread pools with maximum 1 thread available for each.
QThreadPool* persistentThread = new QThreadPool; // no need to write custom thread pool
persistentThread->setMaxThreadCount(1);
persistentThread->setExpiryTimeout(-1);
and then
QFuture<int> future_1 = QtConcurrent::run(persistentThread, func_1);
QFuture<int> future_2 = QtConcurrent::run(persistentThread, func_2);
func_2 will be executed after func_1 in the same one "persistent" thread.
This question already has answers here:
How to execute a functor or a lambda in a given thread in Qt, GCD-style?
(5 answers)
Closed 6 years ago.
I want to call object's slot in its own thread. In other word, to put slot processing into receiver's thread queue.
As I know, it could be done by using
QMetaObject::invokeMethod(objPtr, "someMethod", Qt:: QueuedConnection);
But as for me, this way is unsafe. Because there are no any compile-time checks about existence of method with such name. And in case of some mistype, error will occur only in runtime and only in logs.
Another way is to create dummy signal like
void callObj();
and connect this dummy signal to slot
connect(this, &Obj1::callObj, objPtr, &Obj2::someMethod, Qt:: QueuedConnection);
But this way is looks really bad.
So is there any way to do this?
Thanks in advance for help.
If you have definition of the interface you'll be calling against, you can use a single shot QTimer with 0ms timeout:
QTimer::singleShot(0, obj, &Class::slot);
you can also call it with a lambda
QTimer::singleShot(0, obj, [obj]{ obj->slot(42); } );
This approach requires the target thread to run its own event loop (i.e. QThread::exec()), but since you want to run slots in its thread I assume that's what you want.
It is not unsafe - nothing bad will happen, invokeMethod() will return false if the method doesn't exist. Check the return value to decide further course of action. It won't crash or anything like that.
You can use qobject_cast to make sure your pointer is of the right type, which should be enough to verify if it has the particular method. Other than that, take care not to mistype it and don't use untested code.
Also, consider that there are several other ways to leverage multithreading besides the implicit object thread affinity.
I wouldn't call the dummy signal approach "really bad" - it is just a hack, and hacks go hand in hand with Qt, as huge as the framework might be, it is far from fullproof.
Related to Qt: Do events get processed in order?
Do Qt::QueuedConnection signals always get invoked in order?
So:
void A::func()
{
emit first_signal();
emit second_signal();
}
If these are both connected by Qt::QueuedConnection to slots will they always be invoked in the order first_signal() then second_signal()?
Given the fact that bug(s) regarding the event prioritization are still being fixed very recently (target version 4.8.0), better don't rely on it. The observation that docs avoid any bold statements most probably means that the devs are simply not so sure.
If the documentation does not state it, you should rather not assume it.
This is a pretty basic scenario but I'm not finding too many helpful resources. I have a C++ program running in Linux that does file processing. Reads lines, does various transformations, writes data into a database. There's certain variables (stored in the database) that affect the processing which I'm currently reading at every iteration because I want processing to be as up to date as possible, but a slight lag is OK. But those variables change pretty rarely, and the reads are expensive over time (10 million plus rows a day). I could space out the reads to every n iterations or simply restart the program when a variable changes, but those seem hackish.
What I would like to do instead is have the program trigger a reread of the variables when it receives a SIGHUP. Everything I'm reading about signal handling is talking about the C signal library which I'm not sure how to tie in to my program's classes. The Boost signal libraries seem to be more about inter-object communication rather than handling OS signals.
Can anybody help? It seems like this should be incredibly simple, but I'm pretty rusty with C++.
I would handle it just like you might handle it in C. I think it's perfectly fine to have a stand-alone signal handler function, since you'll just be posting to a semaphore or setting a variable or some such, which another thread or object can inspect to determine if it needs to re-read the settings.
#include <signal.h>
#include <stdio.h>
/* or you might use a semaphore to notify a waiting thread */
static volatile sig_atomic_t sig_caught = 0;
void handle_sighup(int signum)
{
/* in case we registered this handler for multiple signals */
if (signum == SIGHUP) {
sig_caught = 1;
}
}
int main(int argc, char* argv[])
{
/* you may also prefer sigaction() instead of signal() */
signal(SIGHUP, handle_sighup);
while(1) {
if (sig_caught) {
sig_caught = 0;
printf("caught a SIGHUP. I should re-read settings.\n");
}
}
return 0;
}
You can test sending a SIGHUP by using kill -1 `pidof yourapp`.
I'd recommend checking out this link which gives the details on registering a signal.
Unless I'm mistaken, one important thing to remember is that any function inside an object expects a referent parameter, which means non-static member functions can't be signal handlers. I believe you'll need to register it either to a static member function, or some kind of global function. From there, if you have a specific object function you want to take care of your update, you'll need a way to reference that object.
There are several possibilities; it would not necessarily be overkill to implement all of them:
Respond to a specific signal, just like C does. C++ works the same way. See the documentation for signal().
Trigger on the modification timestamp of some file changing, like the database if it is stored in a flat file.
Trigger once per hour, or once per day (whatever makes sense).
You can define a Boost signal corresponding to the OS signal and tie the Boost signal to your slot to invoke the respective handler.