Passing QModelIndex cross Thread queued connection - qt

WMIQuery::wmiquery(WMI::WMITable* table, const QString& query, WMI::ProgressIndicator* progressIndicator)
This is the Function signature. and I am calling it through QtConcurrent::run
QFuture<quint32> future = QtConcurrent::run(WMI::WMIQuery::wmiquery, _table, query);
The architecture is quite simple.
Expected number of rows that will be returned by the query is known.
query is ran parallelly and on each record fetch a row is added to table: WMI::WMITable*
WMI::WMITable is a Simple QObject Table Data Structure .
it emits rowsAboutToBeInserted(QModelIndex, int, int) and rowsInserted(QModelIndex, int, int) upon row addition.
On the other hand ProgressIndicator in instantiated on main thread and the table is passed to its ctor . it gets the expected total number of rows from WMI::WMIQuery::wmiquery() through ProgressIndicator::setRecordCount(quint64 count).
it has a slot rowAdded() which emits the progress out of 100 by doing some simple mathematics. In its ctor it connects
connect(_table, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowAdded()));
What I think. as WMI::WMIQuery::wmiquery() i running on a different thread (on QThreadPool) this connection is a cross thread queued connection . am I correct ?
I am getting the following error at runtime
QObject::connect: Cannot queue arguments of type 'QModelIndex'
(Make sure 'QModelIndex' is registered using qRegisterMetaType().)
What should I do ? as my SLOT(rowAdded()) does not require the 3 arguments of SIGNAL(rowsInserted(QModelIndex,int,int)) should I make another signal like rowInserted() and emit it whenever I am emitting rowsInserted(QModelIndex,int,int) and use this SIGNAL instead for this coinnection
You may ask why I am using model like signals like rowsInserted(QModelIndex,int,int) in the table data structure. cause I do also have a model that is connected to this table. which will also be updated row by row. however I think that is immater in this regard.

Before emitting a signal across a thread boundary with a non-trivial argument type (like QModelIndex), you must first call this:
qRegisterMetaType<QModelIndex>("QModelIndex");
That prepares Qt to be able to emit the signal across a thread boundary.
Normally you would do this in main() or somewhere that only runs once, before calling emit, but after your QApplication has been instantiated.
This is only necessary for types that are non-trivial. For example, a signal like this would not require you to call qRegisterMetaType()
signals:
void mySignal(int foo, int bar);
But a signal like this does require qRegisterMetaType():
signals:
void mySignal(QModelIndex);
For more info, see the Qt docs here: http://doc.qt.nokia.com/latest/qmetatype.html#qRegisterMetaType

I know this is rather late, but I wanted to be sure someone mentioned it: QModelIndex is not meant to be queued, for the same reason that it's not meant to be stored and used later in other ways. That is, if the model changes before you use the QModelIndex, you will get undefined behavior. If you need queued events with model indices, you should probably use QPersistentModelIndex. Not really relevant to the original question, but may be of use to someone who lands here.

Related

When Qt-5 will fail the connect

Reading Qt signal & slots documentation, it seems that the only reason for a new style connection to fail is:
"If there is already a duplicate (exact same signal to the exact same slot on the same objects), the connection will fail and connect will return false"
Which means that connection was already successful the first time and does not allow multi-connections when using Qt::UniqueConnection.
Does this means that Qt-5 style connection will always success? Are there any other reasons for failure?
The new-style connect can still fail at runtime for a variety of reasons:
Either sender or receiver is a null pointer. Obviously this requires a check that can only happen at runtime.
The PMF you specified for a signal is not actually a signal. Lacking proper C++ reflection capabilities, all you can do at compile time is checking that the signal is a non-static member function of the sender's class.
However, that's not enough to make it a signal: it also needs to be in a signals: section in your class definition. When moc sees your class definition, it will generate some metadata containing the information that that function is indeed a signal. So, at runtime, the pointer passed to connect is looked up in a table, and connect itself will fail if the pointer is not found (because you did not pass a signal).
The check on the previous point actually requires a comparison between pointers to member functions. It's a particularly tricky one, because it will typically involve different TUs:
one is the TU containing moc-generated data (typically a moc_class.cpp file). In this TU there's the aforementioned table containing, amongst other things, pointers to the signals (which are just ordinary member functions).
is the TU where you actually invoke connect(sender, &Sender::signal, ...), which generates the pointer that gets looked up in the table.
Now, the two TUs may be in the same application, or perhaps one is in a library and the other in your application, or maybe in two libraries, etc; your platform's ABI starts to get into play.
In theory, the pointers stored when doing 1. are identical to the pointers generated when doing 2.; in practice, we've found cases where this does not happen (cf. this bug report that I reported some time ago, where older versions of GNU ld on ARM generated code that failed the comparison).
For Qt this meant disabling certain optimizations and/or passing some extra flags to the places where we know this to happen and break user software. For instance, as of Qt 5.9, there is no support for -Bsymbolic* flags on GCC on anything but x86 and x86-64.
Of course, this does not mean we've found and fixed all the possible places. New compilers and more aggressive optimizations might trigger this bug again in the future, making connect return false, even when everything is supposed to work.
Yes it can fail if either sender or receiver are not valid objects (nullptr for example)
Example
QObject* obj1 = new QObject();
QObject* obj2 = new QObject();
// Will succeed
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
delete obj1;
obj1 = nullptr;
// Will fail even if it compiles
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
Do not try to register pointer type. I've used the macro
#define QT_REG_TYPE(T) qRegisterMetaType<T>(#T)
with pointer type CMyWidget*, that was the problem. Using the type directly worked.
No it's not always successful. The docs give an example here where connect would return false because the signal should not contain variable names.
// WRONG
QObject::connect(scrollBar, SIGNAL(valueChanged(int value)),
label, SLOT(setNum(int value)));

Qt Signals and Slots with Boost::smart_ptr

So what I am trying to do is use Qt signals and slots to pass around an image through a smart_ptr so that it will delete itself when everything that needs to use the data is done accessing it.
Here is the code I have:
Class A, inherits QObject:
signals:
void newImageSent(boost::shared_ptr<namespace::ImageData> &image);
Class B, inherits QObject:
public slots:
void newImageRecieved(boost::shared_ptr<namespace::ImageData> &image)
{
// Manipulate Image
}
Connection Code:
QObject::connect(classAPtr.get(),
SIGNAL(newImageSent(boost::shared_ptr<namespace::ImageData>)),
classBPtr.get(),
SLOT(newImageRecieved(boost::shared_ptr<namespace::ImageData>)),
Qt::QueuedConnection);
When I try to do the connection is always returns false though, so is there something I am missing?
In a queued connection the signal is queued in the event loop and its parameters are copied.
Therefore the slot is not directly executed.
To make copying possible you have to register the type via qRegisterMetaType, see also here.
Since you are using shared pointers easiest solution would be to transmit them by value, then you would not have to bother with the references as Frank Osterfeld pointed out.
The way you create the connection is string based and as result is easy to get wrong, especially when namespaces are involved.
Using typedef would ease the pain a little and make it easier to spot errors.
For example you could do
typedef boost::shared_ptr<namespace::ImageData> ImageDataPtr;
and use ImageDataPtr from then on.
Especially on registering the type as meta type which you have to do since you are using a queued connection.
If you are using Qt5 then you can rely on the new connection syntax which ensures correctness during compilation as it does not rely on string comparisons:
QObject::connect(classAPtr.get(), &A::newImageSent,
classBPtr.get(), &B::newImageRecieved,
Qt::QueuedConnection);

When to use deleteLater

Assuming I have the following snippet, is it safe to call deleteLater in qto's destructor for other QT objects it might administer?
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyQTObject qto;
qto.show();
return a.exec();
}
Because I've analyzed similar code like this with a leak detector and all the objects for which deleteLater was called, weren't deallocated correctly unless I replaced the call with a normal delete.
If I've understood this correctly, deleteLater only registers a deletion event in the QT message queue. Can this be the problem that qto's destructor is called at the end of main's scope whereas the QT message loop already ends with the return from a.exec? Thus the deletion event will never be processed, in fact not even pushed into a message queue since there is none?
This post is rather aged, but I would like to add the answer I would have liked to come across when I was asking this myself.
deleteLater() can be very useful in combination with asynchronous operations. It especially shines, I think, with the more recent possibility to connect signals to lambda functions.
Suppose you have some longComputation() that you want to execute asynchronously (not in the sense of multithreading, in the sense of scheduling execution in the event loop). You can do like this:
void MyClass::deferLongComputation()
{
QTimer* timer = new QTimer();
connect(timer,
&QTimer::timeout,
[this, timer](){this->longComputiation(); timer->deleteLater();});
timer->setSingleShot(true);
timer->start();
}
where deleteLater() takes care of safely disposing of the QTimer once its duty has been carried out and avoid the memory leak that one would have otherwise.
The same pattern can be used in multithreading with QFutureWatcher.
As I understand it, deleteLater is most often used when you require an object to be deleted from within the call to a slot. If delete is used in this case and the object is referenced when returning from the slot, a reference to uninitialised memory occurs.
Therefore, deleteLater requests that object to be deleted by placing a message on the event loop, which is processed at some point, on returning from the slot and it is safe to be deleted.
I expect that using deleteLater in the destructor means there's a likely chance that the object goes out of scope, calls deleteLater on its managed objects, but quits before the event loop has a chance to delete the objects, as exiting from QApplication::exec() will terminate the event loop.
The question is old, but I'll leave this for the future generation)
The reply which was marked as an answer is correct but oddly formulated.
Actually your question contains a right answer:
message loop already ends with the return from a.exec? Thus the
deletion event will never be processed, in fact not even pushed into a
message queue since there is none.
This is exactly what is happening. Everything deleteLater() does is just posting a deletion event into the outter event loop. When event gets proccessed - object gets deleted. But if there are not outter event loop and no event loop is encountered later in the execution flow - event will never get posted, thus object is never deleted.
If you call deleteLater() in the object's destructor and put an object on the stack - deleteLater() is called when the object goes out of scope. In your example "going out of scope" is happening when closing brace of main() function is encountered. However, by that time, a.exec() (which represents the main event loop of Qt App) has already returned --> no event loop any more --> deleteLater() was called, but it's nowhere to post a deletion event --> objects were supposed to be "deletedLater" never get deleted...
Regarding the part "when to use deleteLater()":
Kuba Ober answered:
Generally speaking, there is a narrow set of circumstances where
deleteLater should be used. Most likely you simply shouldn't be using
it...
Don't listen to it, it is absolutely incorrect as the whole answer. What you should do and what should not you better decide after reading this article. Although, it is mainly about Qt threads, the article also tells about ascynchronous programming (and, as Emerald Weapon mentioned, it is exactly what deleteLater() was created for).
Also, smart pointers and QObject parent ownership have nothing to do with scheduling for the deletion with deleteLater(). These both techniques are actually using a simple delete operation under the hood. And as the article shows and as Emerald Weapon's answer demonstrated: delete does not solve the problems deleteLater() does. So if you need to delete object you use delete, if you need to schedule it for the deletion you use deleteLater().
BTW, if you want to use smart pointer with deleteLater() you can specify the deleter:
// Shared Pointer
QSharedPointer<MyObject> obj =
QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
// Scoped Pointer
QScopedPointer<MyObject, QScopedPointerDeleteLater> customPointer(new MyObject);
And at last, It is an NOT an error to use deleteLater() in the destructor of QObject, for non-child objects.
You are correct that the deleteLater() command is only executed by an event loop.
From the Qt documentation for QObject:
Schedules this object for deletion.
The object will be deleted when control returns to the event
loop. If the event loop is not running when this function is
called (e.g. deleteLater() is called on an object before
QCoreApplication::exec()), the object will be deleted once the
event loop is started. If deleteLater() is called after the main event loop
has stopped, the object will not be deleted.
Since Qt 4.8, if deleteLater() is called on an object that lives in a
thread with no running event loop, the object will be destroyed when the
thread finishes.
Note that entering and leaving a new event loop (e.g., by opening a modal
dialog) will \e not perform the deferred deletion; for the object to be
deleted, the control must return to the event loop from which
deleteLater() was called.
Note: It is safe to call this function more than once; when the
first deferred deletion event is delivered, any pending events for the
object are removed from the event queue.
If you want all child QObjects to be deleted when qto is deleted, make sure they are created with qto as a the parent.
Generally speaking, there is a narrow set of circumstances where deleteLater should be used. Most likely you simply shouldn't be using it.
It is an error to use it in the destructor of QObject, for non-child objects. As you've found QObjects may well be destructed without an event loop present. There are no deleteLater calls in object destructors the qtbase Qt module, for example.
One has to be careful here: for example, ~QTcpServer() invokes close() invoking d->socketEngine->deleteLater(), but the socket engine is already a child of the server and will be deleted by ~QObject() anyway.
For all I know, MyQTObject should be doing one of the following:
using a smart pointer like QScopedPointer or std::unique_ptr,
have the objects as regular (non-pointer) members,
use raw pointers and have the objects be children of it.

QT - Understanding following lambda expression for a SLOT

I am currently trying to understand the new QT5 signal/slot syntax
connect(sender, &Sender::valueChanged, [=](const QString &newValue) {
receiver->updateValue("senderValue", newValue);
});
Now my question is where is the address of the receiver SLOT in the above expression ? I wanted to know this because what happens if a signal is in threadA and the slot is in thread B and I wanted it to be a queued connection ?
A slot is a piece of code, it doesn't "live" in a thread - a thread might run it or not, but the code itself doesn't belong to any thread. (If the slot is a member function, then the Qt object defined as the receiver belongs to a Qt thread - that's a property of the object, not the function.)
In the code you have above, the compiler generates an object that:
captures receiver by value ([=])
has a function-call operator that can be called with a reference to a const QString.
That object is passed to connect along with the other two arguments. It's not a QObject, so it doesn't have an owning thread in the Qt sense. What you need to make sure of is that:
what receiver points to stays alive for as long as that signal is connected
receiver->updateValue(...) is thread-safe - it will be called in sender's context/thread.
If receiver->updateValue needs to be called in receiver's thread/context, then do not use that syntax for the connect call, use the one where you specify both sender and receiver, and the connection type.

qt connectNotify usage

I have a QT class instance, called C, (C inherits QOBJECT) that sends a signal S.
In my program, other QT classes instances X are created and destroyed when the program runs. These other classes connect and disconnect S, i.e. they run:
connect(C,SIGNAL(S()), this, SLOT(my_func())); // <this> is an instance of X
or
disconnect(C,SIGNAL(S()), this, SLOT(my_func()));
In class C, the calculation of whether S should be emitted (and the data associated to it - not shown here) is rather complicated, so I would like the instance of class C (which emits the signal) to be notified when one(or more) object are connected (listening) to S or when all are disconnected.
I have read about the connectNotify and disconnectNotify functions, but their usage is discouraged. Besides the documentation does not state very clearly if there is a one to one relationship between the number of (dis)connectNotify calls and the number of "listener" to the signal (or can one single connectNotify be called for more than one listener?).
Can I just count positively (count++) the number of connectNotify and negatively (count--) the number of disconnectNotify and just react to non-zero value?
Any better way to do this?
First, I think you've got it right that connectNotify and disconnectNotify can be used for this purpose - each connect event will be counted properly, even if it is a duplicate from the same object.
You can also double check this with QObject::receivers
int QObject::receivers ( const char * signal ) const [protected]
Returns the number of receivers connected to the signal. Since both
slots and signals can be used as receivers for signals, and the same
connections can be made many times, the number of receivers is the
same as the number of connections made from this signal. When calling
this function, you can use the SIGNAL() macro to pass a specific
signal: if (receivers(SIGNAL(valueChanged(QByteArray))) > 0) {
QByteArray data;
get_the_value(&data); // expensive operation
emit valueChanged(data); } As the code snippet above illustrates, you can use this function to avoid emitting a signal that
nobody listens to. Warning: This function violates the object-oriented
principle of modularity. However, it might be useful when you need to
perform expensive initialization only if something is connected to a
signal.
My suggestion would be to write a simple test program. Override connectNotify and disconnectNotify to increment/decrement a counter, but also use receivers to verify that the counter is correct. Try connecting multiple times, disconnecting multiple times, disconnecting even if there is no connection, etc.
Something to be careful of: connect and disconnect are thread-safe; I'm not sure if the matching Notify functions are safe also.
Since Qt 5.0, you can do this more easily with the QObject::isSignalConnected function. Example from the documentation:
static const QMetaMethod valueChangedSignal = QMetaMethod::fromSignal(&MyObject::valueChanged);
if (isSignalConnected(valueChangedSignal)) {
QByteArray data;
data = get_the_value(); // expensive operation
emit valueChanged(data);
}

Resources