I have the following function that is called each time a user click a button :
void Foo::onCommand1Clicked(int index)
{
connect(this, &Foo::authorized, this, [=]() {
// avoid multiple connections
QObject::disconnect(this, &Foo::authorized, this, nullptr);
// do work based on "index" captured by value ( or other parameters in real code )
this->processCommand1(index);
// ..
}
});
}
Now, if the command is "authorized" ( the signal is asynchronously emitted but may also not be emitted at all), then the lambda containing the command logic is executed.
Moreover, while the command is pending for authorization, the button is disabled ( preventing the function to be called )
My question is about the lambda connected to the signal and especially its parameters captured by value : Are those parameters eventually released from memory or do they accumulate into the memory stack each time the connection is done (ie the button is clicked) ?
More generally, is there any kind of "memory leak" or "continuously growing stack" in this code ?
Thank you.
for lambda connections in Qt third parameter called context is used. In your case is this pointer. So, while this is alive, connection is active. When you create a lambda connection, lambda object is moved as a whole object to connection manager. When you disconnect from your signal, lambda object should be dead (as i suggest). Maybe it's deleted later. So I reccomend to insert disconnect as last instruction in lambda. However, this is still alive.
A also recommend you to use another mechanism to call async task, than connecting/disconnecting to a signal in the same object!
A thread, for instance. Or to call QTimer::singleShot. I don't see in what circumstances authorized signal is emitted
Related
I would like to understand a simple piece of code I came across. It is a connection between an object of the interface and two signals.
The code is:
connect( ui->checkbox_legEnabled,
SIGNAL( stateChanged( int ) ), SIGNAL( edited() ) );
What is the meaning of this line of code?
Thanks,
Sara
With Qt signals and slots, you can directly connect one signal to another signal (or non-signal member function), without having a slot in between. See connection function invoked here is this overload of QObject::connect.
This line of code hence means, whenever the object ui->checkbox_legEnabled (presumably some kind of QCheckbox) emits the stateChanged signal (that has an int parameter passed along), directly emit another signal (or ordinary member function) edited (without parameters).
Short answer is you can connect a signal to another signal and that means that the second signal will also emit whenever the first signal is emitted, read more about signals and slots in the documentation here, also check out the new way to call connect (with function pointers)
Now in your case what it does it's basically allows you to keep the ui private, but in the same time forward the signals you want to the outside of your object, by allowing other objects to connect to the signal(s) you provide in the interface.
Incomplete usage example (based on your code, i named the class that contains your code MyWidget): the main-window (or whoever) that has access to your widget can be notified whenever something changes inside, by connecting to the edited signal:
void MainWindow::createMyWidget()
{
m_myWidget = new MyWidget(this);
connect(m_myWidget, &MyWidget::edited, this, &MainWindow::myWidgetWasEdited));
}
This way whenever something changes inside MyWidget the MainWindow can be notified about the edit and it can take the necessary actions inside the myWidgetWasEdited slot.
This can be expanded, if needed, to provide an signal for each particular "edit" instead of a single generic edited signal (but this depends on your needs).
I am new to Qt. I have worker thread that is an std::thread. The worker thread function continuously fetches some some data in a loop. The size of the data is frequently updated on a Text element on a QML UI. I have a listener callback which is nothing but an std::function and it gets called from the thread's function. It sends me callbacks based on which I updated the Text element on QML. I update it using signal slot mechanism.
Following is the QML : Text element:
Text {
id: mytext
objectName: "mytextobject"
function slotUpdateData(someValue){
mytext = someValue
}
}
SignalUpdateData is connected with slotUpdateData which resides on QML side. Every time I get the data event callback from the std::thread, I emit SignalUpdateData which updates the QML Text element on UI.
void CallBackReceivedFromWorkerThread(float someValue) {
emit SignalUpdateData(someValue)
}
Following is how I have connected this C++ signal with the QML slot
QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));
And all of this works fine. No crashes, lock-ups, nothing.
As per my understanding, since the worker thread's function is triggering the callback, the execution control is on the worker thread when the callback is received. So when doing emit SignalUpdateData(someValue), we'er still on the worker thread. And as far as I know from my previous experience in android & java, we cannot update the UI from anywhere outside the main thread of the application.
So, How is this working ? Is emit SignalUpdateData(someValue) putting the call into the main UI thread's event loop ? Is Qt still making the UI change on main thread in spite of me calling for it from a worker thread ? If my approach is fine, then does it have performance implications ? What is the best recommendation to do this ?
I want to be very sure about this & not just lucky about making this to work. Should I use a Qt::Connection_enum as well for best approach ?
You're leveraging Qt the way it was meant to be! And you've run into it accidentally: that's a sign of a decent design - it "just works". Hooray for you, hooray for Qt :)
It's working because Qt has been designed specifically to make it work, and you're using the default automatic connection whose raison d'ĂȘtre is to help you out in this specific case. So you happen to be doing everything right: change nothing!
When you emit a signal, Qt acquires relevant source and destination object mutexes, and compares the receiving object's thread() to QThread::currentThread(). If they are identical, the slot/functor is called immediately: it happens in the body of the signal, so the slot is called before the signal returns. This is safe as the target object is used from its thread(), where it's safe.
If target->thread() != QThread::currentThread(), then a QMetaCallEvent is queued to the target object. The event contains the (equivalent of) slot method pointer and a copy of any parameters passed by the slot. The QObject::event implementation handles the event and executes the call. The target object thread's event loop is on the call stack, since its job is to deliver the queued events to the object.
The above is, in a nutshell the meaning of a Qt::AutoConnection. If you're using Qt::QueuedConnection, the 2nd case applies no matter what the threads are. If you're using Qt::DirectConnection, the 1st case applies no matter what.
My guess is that >95% of the uses of a non-automatic connection type in Qt-related questions on SO are unnecessary and stem from lack of understanding and resorting to what amounts to magic incantations.
Does Qt offer functionality to know the number of queued signals that are pending for a given slot to process? Is there a way to clear them? For example, if several emits are done on a signal connected to a given slot, how could someone know the amount of these emitted signals?
QMetaObject::Connection class has a laconic interface and does not seem to offer related functionality. Deleting the object that receives the signals, hence destroying the connections, solves the problem. But is there a way to do this without disconnecting the slots or deleting the receiving objects?
The reason you ask the question most likely indicates that your design is broken. The signals and slots are a mechanism to decouple code. The objects connected together should behave themselves no matter how many senders or receiver are there, and certainly shouldn't attempt to track such matters!
It'd be wiser to fix the issue at the source by altering the design. If you are uffering from an event storm e.g. due to changing a widget's data in a slot, the slot should be very lightweight and only schedule an update of the widget by calling update(), but never forcing an immediate repaint. This leverages repaint event compression done by Qt. You might wish to compress your own events too.
Connection types in Qt
Signals and slots in Qt can be delivered using a direct, queued or blocking connection. The automatic type is not really a fixed connection type. It is an instruction to resolve the type for every receiver, at every signal emission into either a direct or queued type.
The direct connection is like any indirect function call: nothing is queued, and the slot is called from within the body of the signal method:
// all direct-connected slots/functors are invoked before mySignal() returns
emit mySignal();
The queued connection posts a QMetaCallEvent to the receiving object thread's event loop. That event contains the arguments of the call, or carries the functor. Is is handled by QObject::event(). You can certainly intercept such events. For details, see this question.
As far as I know, it is not possible to access the queue.
First of all, if the slot is in a QWidget subclass, in the GUI thread, then you can just update the member variables and call update(), and then just use the current values in paintEvent() when it gets called. These are automatically compressed, so there will be just one repaint event, no matter how many times update() gets called.
However, if the slot is not related to painting, or not in the GUI thread at all, then you need something else.
A simple solution to many cases needing this is to use a 2nd slot and a single-shot QTimer with delay 0 (or even longer delay if desirable).
Here's some example code, which should give you the idea of what I mean:
// in constructor, set mActualSlotTimer to
// singleshot, interval 0, parent this (needed for multi-threaded use)
// and connect timeout() to privateActualSlot()
// public slot for receiving the signal from outside
void MyClass::actualSlot(int data) {
// class member to store the new data value until it can be set
mNewData = data;
// restart the timer, no matter if it was already running or not
mActualSlotTimer.start();
}
// "private" slot for actually doing the change
void MyClass::privateActualSlot() {
// maybe useful: if (this->mData == this->mNewData) return;
mData = mNewData;
// do whatever else needs to be done!
}
Obviously, if your public slot does not actually take any parameters, then you don't need mData and mNewData.
One thing to note about this approach is, it works on all connections, it's not limited to just Qt::QueuedConnecton. As a consequence, it also makes using Qt::BlockingQueuedConnection kinda pointless.
A disclaimery note: I briefly checked Qt source code and it seems using timer with interval 0 should be ok: restarting the timer will work as expected. But if there still seems to be too many calls to privateActualSlot, then providing a suitable interval might be necessary. I have usually wanted a little delay (5 ms for example) to throttle things down a bit more than "as often as possible", so have not tested this extensively with interval 0.
I have developed an app in Qt/C++, I have used signal/slot mechanism to interact between 2 threads. the first thread run the UI/TreeWidget and the second one run the framework
I got an issue on one action.
In the UI side, before starting my action, I'm connect signal/slot between UI and framework such as below in the treewidget.cpp
connect(&m_Framework, &Framework::RequestIfNameExist, this, &TreeWidget::RequestIfNameExist);
connect(this, &TreeWidget::SendAnswerIfNameExist, &m_Framework, &Framework::NotifIfNameExist);
The framework, start and send the RequestIfNameExist:
emit RequestIfNameExist(tmpname, item, fileInfo.isDir());
while(WaitingResponse == false){
usleep(200);
}
I have added a loop because I need to wait the feedback. Strange things is that in the treewidget.cpp, I never enter in
void TreeWidget::RequestIfNameExist(QString name, TreeWidgetItem *parent, bool isFolder) {
#ifdef PULS_LOG
QLOG_INFO() << "[TreeWidget] [RequestIfNameExist] ";
#endif
emit SendAnswerIfNameExist(isNameExist(name, parent), isFolder);
}
I never access to RequestIfNameExist in the TreeWidget but the signal is emitted.
I have also put a while loop in the framework to wait the feedback from TreeWidget
void Framework::NotifIfNameExist(QTreeWidgetItem *item, bool isFolder){
if(item != NULL)
item->isFolder = isFolder;
WaitingResponse = true;
}
Any idea why the signal emitted by framework never arrived on the treewidget ? is it coming from the while ??
Is there a way to not use while such as a "wait event" + timeout
Thanks
My first thought is that having either thread block until an operation in the other thread completes is a poor design -- it partially defeats the purpose of having multiple threads, which is to allow multiple operations to run in parallel. It's also liable to result in deadlocks if you're not careful (e.g. if both threads decide to emit-and-wait at approximately the same time!)
A better design would have the initiating method do the emit RequestIfNameExit and then return immediately, so that the initiating thread's event loop can continue running as usual during the operation. Then, when the other thread has done its work, it responds by emitting its own response-signal, causing the appropriate/connected slot-method in the first thread to be called, at which point the results are handled back in the first thread.
That said, if you insist on wanting to block the execution of the signal-emitting thread inside a method, until the other thread has finished executing the associated slot-method, you can get that behavior by setting the signal/slot connection's type to be Qt::BlockingQueuedConnection (the connection type can be specified via an optional extra argument to connect()). If you do that, then you emit call won't return until the slot-method (in the other thread) has finished executing. Given that, you can get the results from the other thread by passing a pointer to a data object as one of the arguments in the signal/slot method signature, and having the other thread populate that data object as necessary. When the emit returns you can just examine the contents of that data object to see the results.
I am learning Qt framework (C++) and was wondering if QT has any mechanisms to protect slots from being called before an object is fully initialized.
Consider Class A constructor:
A::A() {
mTreeView = new QTreeView();
...
connect(mTreeView, &QTreeView::customContextMenuRequested,
this, &A::OnContextMenuRequested);
...
}
My worry is the user would be able to right-click on the tree-view before A's constructor has finished. Another context is as follows:
A::A() {
mQObj = new MyQObject();
connect(mQObj, &MyQObject::SomeEvent, this, &A::OnEvent);
}
A::InitB() { mB = new B(); }
A::OnEvent() { mB.doSomething(); }
Here, the doSomething() method can be called before InitB() runs.
Do I have to worry about such scenarios? And if so, is there a way to avoid these issues without having to initialize all your objects first, then going back and connecting the events afterwards separately?
You don't have to worry about such scenarios in most cases, because events are delivered in the same thread. There's no "hidden multithreading" going on you have to care about. If you don't explicitly call a function in the constructor of A that causes events to be processed, you're safe and your current method, slot etc.'s execution is completed before the next event is processed.
That said, the cases where a new event is processed and thus other code (event handlers, slots) is executed, are:
the execution of the current event handler, slot etc. is finished (the code where you create A) and Qt returns to the event loop to wait for the next event. In your case, that's after the A instance is fully constructed.
you start a local event loop (Create a QEventLoop object and call exec())
you call QCoreApplication::processEvents()
you call exec() on a QDialog
1) is the normal mode Qt operates in: You start app.exec(), which starts the event loop. Everything after that is directly or indirectly triggered by an event (user input, timer, I/O). Event happens and is added to the event loop's event queue. The event loop calls the event handlers for the event. When the event handlers are completed, the event loop picks the next event and calls the handlers for it.
So everything happens in an orderly fashion, one event after another, unless one of the event handlers (say, a slot listening to a button's clicked() signal) does one of 2, 3 or 4. Then Qt processes the next event in-place, .i.e. where exec() or processEvents() is called. The event handlers/slots are executed accordingly. Then exec()/processEvents() returns. Now all the certainties one would have without calling exec()/processEvents() are gone, unfortunately: The user could have done random stuff, things could be arbitrarily changed or deleted (even the this pointer, if the user closed the window, for example). Thus especially 2) and 3) are error-prone and usually lead to major headaches, so I would avoid them whenever possible, or at least be aware of the potential issues.
Now there's the case that you use multithreading yourself. As all the actual UI and related user events is handled in a single main thread, multithreading here usually means that you have threads doing non-UI work and that interacts with your UI thread by calling functions on objects living in the UI thread, modifying data shared by both threads, or using cross-thread signal/slot connections.
If you don't use signal/slots but direct method calls from the secondary thread to the UI thread or modify shared data, the usual multithreading rules apply: Things will go majorly wrong unless you know what you're doing and use synchronization accordingly. Qt's UI classes aren't thread-safe.
If you use signal/slots, the calls are /queued/, i.e. if thread B emits a signal and you receive it in a slot in your main thread, the call of the slot is delivered in the same manner as a user event: the same rules as for user events apply. Unless you do one of 2, 3, 4, the slot won't be called before your event handler/slot returns. So cross-thread signal/slots connections are a way of /message passing/ where the messages are delivered via the event loop.