What benefits does QT get with normalized signature - c++

I read that QT applies signature normalization process on the signal/slot mechanism. MOC generator basically removes the const reference qualifiers from signals/slots and just pass them by value.
I have a class which generates a big data structure called BIG_DATA so frequently and some other classes need to catch this data structure every time it is emitted.
struct BIG_DATA
{
// very big data
};
class DataGenerator
{
// some methods which generate BIG_DATA
signals:
void data_updated(const BIG_DATA &);
};
What i do :
connect(&data_generator_object, SIGNAL(data_updated(const BIG_DATA &)), this, SLOT(catch_new_data(const BIG_DATA &)));
What QT does :
connect(&data_generator_object, SIGNAL(data_updated(BIG_DATA)), this, SLOT(catch_new_data(BIG_DATA)));
So, what is the benefit of removing const reference qualifiers here ? What am i going to do with the overhead of copying the whole BIG_DATA to many clients of data_updated signal ?
Seems like the best way is to use a pointer to the generated BIG_DATA object, if QT doesn't attempt to remove the pointer signature too.

Signature normalization is used only to identify signals and slots. That is, if you want to tell connect() which signal or slot to use, you need to pass normalized signature there. But your signal's and slot's signatures remain untouched. If you use direct connection (which is default for single-threaded program), your object will not be copied.

If you are using queued connections, your structure is copied anyway (see this).
Now, if you use use normalized signals, you can minimize performance hit when you are using connect (see this) :
Lookup is first attempted with the signature as-is, and only if that fails is QMetaObject::normalizedSignature() called.
That means, when using non-normalised signal/slot signatures, you not only pay for a strcpy(), but also for a doomed-to-fail first lookup attempt. Sure, connects are usually done during startup, and a profiler won’t show you, but using non-normalised signatures is hereby firmly put into the realm of premature pessimisation.
However, the performance hit is only when using connect, not when sending signals. And the connections are made usually only once. Therefore I wouldn't worry too much.
In order to avoid the structure copy, use references.

Related

For a NOTIFY signal on a property, what difference does it make if I give it a parameter?

Suppose I have a class that looks like this:
class Something : QObject {
Q_PROPERTY(int something READ getSomething NOTIFY somethingChanged)
// ...
signals:
void somethingChanged();
}
According to the documentation, declaring somethingChanged as void somethingChanged() and void somethingChanged(int) (note the parameter) are both valid. Why would I want to do it one way over the other?
Emitting the value allows you to use that value without having a reference to the object it is a property of. It is how things are usually done in the C++ API, this saves you from manually having to keep references to objects, so that you can read in the value upon a change notification. Note that even then, you can use QObject::sender() to find the sender object if necessary, but emitting the value is just more straightforward.
In QML what you end up using most of the time is bindings, which are very fast and powerful, and involve having references to the objects, and change notifications cause the binding expressions which reference the properties to automatically reevaluate. Thus it is not necessary to emit the actual value.
There is nothing stopping you from having the best of both worlds. A notification signal that emits the new value appears to work just fine with QML bindings. So if for some reason you need to emit a value, don't shy away from it, it will not jeopardize QML compatibility.

Qt signal and slots: are reference arguments copied?

In qt framework, most library signals and slots use pointers as parameters. I was wondering, If I create a signal-slot "structure" that takes a reference as the parameter instead of the pointer, will the whole parameter be copied, or just 4 bytes (32-bit system) like in a regular c++ reference?
I am asking this because I noticed something when I create a signal/ slot methods with the reference parameter. When I then connect them, the autocomplete mechanism in QTCreator doesn't hint me with reference parameters like he would do with pointer parameters. He hints me with the regular parameter. For example:
I create a signal and slot:
...
signals:
void mySignal(int& parameter);
private slots:
void on_mySignal(int& parameter);
I then attempt to connected them and Qt doesnt add & for reference in parameter:
...
connect(this, SIGNAL(mySignal(int)), this, SLOT(on_mySignal(int)));
I have to manually change to:
connect(this, SIGNAL(mySignal(int&)), this, SLOT(on_mySignal(int&)));
Thus I am wondering, does reference even work with signal/slot? I would appreciate all help.
If you send and receive a reference, on the same thread, per default no copy will be made. If you do anything else, including sending/receiving a value or sending a reference to another thread, one, two or even three copies will be made.
What happens depends on the connection type and the assurances QT needs to know that references remain valid through the call. A direct connection on the same thread resolves to a simple function call, so very little can happen to the underlying data. A queued connection, however, offers no guarantees for when the call will actually happen, therefore QT will make copies to preserve data integrity. QT implicitly queues signals crossing thread boundaries.
If either side is pass-by-value then QT copies the data to not affect the underlying object's state.
For more information, have a look at this blog post.

Are signals and slots syntactic sugar or there is more to them?

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!

Using Qt signals and slots vs calling a method directly

Lets say I have a main window with a slider and a widget inside that window with a method called setValue(int). I'd like to call this method every time the value of the slider has changed.
Is there any practical difference between the two following ways of achieving it:
1
void MainWindow::on_slider_valueChanged(int value)
{
ui->widget->setValue(value);
}
2
// somewhere in constructor
connect(ui->slider, SIGNAL(valueChanged(int)), ui->widget, SLOT(setValue(int)));
For me the first approach looks better, because it possibly avoids some overhead related to signals and slots mechanism and also, allows me to process the value before sending it to widget, if there's a need for it.
Are there any scenarios where the second solution is better?
Both approaches use signal-slot connections. In the first case, the connect call is made by QMetaObject::connectSlotsByName() called from setupUi. In the second case, you explicitly call connect yourself.
Also, the first approach is unnecessary in Qt5 when using C++11. You can modify the value in a lambda:
QObject::connect(ui->slider, &QAbstractSlider::valueChanged,
[this](int val){ ui->widget->setValue(val*2); });
To protect from deletion of ui->widget, you should use a QPointer:
class MyWindow : public QMainWindow {
QPointer<QAbstractSlider> m_widget;
...
public:
MyWindow(QWidget * parent = 0) : QMainWindow(parent) {
...
setupUi(this);
m_widget = ui->widget;
QObject::connect(ui->slider, &QAbstractSlider::valueChanged,
[this](int val)
{
if (!m_widget.isNull()) m_widget->setValue(val*2);
});
The overhead of signal-slot connections is quantified in this answer.
Signal/slot advantages:
multiple slots can be connected to single signal, and you don't bother with allocating and freeing memory for this
you can handle multithreading with this
Signal/slot drawbacks:
a little slower than direct call
significantly slower if the slot is virtual
QObject is rather heavy thing, so you usually try to avoid constructing billions of them
More details are available here
The main difference, in your example, of using a signal instead of a direct call, is to allow more than one listener.
If you directly call your widget setValue(), then only that one widget will receive the C++ signal.
If you use a Qt signal, now any other object can connect to receive the event whenever it occurs.
If you do not foresee any other object to ever want to receive the value by signal, I would not bother with such. A direct call is definitively a lot faster (between 3 and 6 CPU instructions instead of dealing with strings to find receivers!), but as Paranaix mentioned, in a GUI it may not be much of an issue (although in this case it could become a problem on older computers if you send all those signals while moving the sliderbar.)
I prefer the second method, since it happened that I forgot to delete the "auto-connect-slots" when the UI-element was removed, causing dead code. AFAIK it is the same "behind the scene" (look at the auto-generated qt-files).
When you would like to modify the value I would prefer following method:
connect(ui->slider, SIGNAL(valueChanged(int)), this, SLOT(myOwnSlot(int)));
void MainWindow::myOwnSlot(int value) {
/** do stuff */
ui->widget->setValue(value);
}
Greetz
Signals & Slots is a different coding style. You can do things with signals that can be useful and neat work arounds to traditional c++. For example you can emit const signals from const functions and have them connect to non const slots (where as in c++ you cannot make non const calls from a const function). I've never liked using mutable objects, so signals provide a clean work around for me.

Qt using boost::shared_ptr in a signal/slot

Is it possible, and if so, how can I create a signal/slot in Qt that is a const reference to a shared_ptr? I want a signal that looks like this:
void signal( shared_ptr<SomeClass> const & )
I know how to do this without a constant reference, that is simply the type shared_ptr<SomeClass> but for efficiency* reasons I'd like to avoid the copying. The same syntax for reference type isn't working:
Q_DECLARE_METATYPE(shared_ptr<SomeClass> const &)
qRegisterMetaType<shared_ptr<SomeClass> const&>();
Many of the standard APIs have QString const & so I assume it is fundamentally possible and I just can't figure out the syntax.
**The biggest problem for performance is not the copying time, but the amount of mutex locking/unlocking as the object is copied to every receiver -- there are lots of them. As multiple threads use the object this introduces a noticeable slow-down/bottleneck. If the shared_ptr does in fact just use an atomic op this cost is also trivial, the general question about const reference in signals remains however.*
So far I have found that I can simply do this:
Q_DECLARE_METATYPE(shared_ptr<SomeClass>)
qRegisterMetaType<shared_ptr<SomeClass> >();
qRegisterMetaType<shared_ptr<SomeClass> >("std::shared_ptr<SomeClass>const&");
I'm trying to verify now whether this truly works correctly. The documentation here isn't clear on what actually happens. It appears that the const reference type in a signal/slot will just be marshalled as a normal shared_ptr<SomeClass>, which is totally okay here. Having some sort of guarantee that this is supposed to work as such would be nice however.
I have the feeling that the simple shared_ptr<SomeClass> version is all that is needed and it is the boost namespace that is interfering with the signals. The second version appears just to register the signal in the global namespace for easier use.
I can confirm, from testing, that the const & part is, as alluded to, completely ignored in queued connections. Each connected slot gets a new copy of the object. This is very unfortunate. :(
Further tests show that the & is used for the slot, but in an unusual fashion. The copy of the object is still created for the queued connection, but if you don't use a reference another copy will be created for the call.
Thus there although every connect will end up copying the data for a queued connection, the references still help a bit. And also if you do have a few signals sent locally (same thread) you may avoid even more copying.
According to one of the answer in this question Argument type for Qt signal and slot, does const reference qualifiers matters? , for a queued connection, the object is copied regardless of how you connect the signal and slot.
Since you are using multiple threads, the connection is queued. If you fear the mutex cost, try using SomeClass * directly.
For the sake of completeness, I believe it should be mentioned that Qt has its own shared pointer implementation, QSharedPointer, which behaves exactly like std::shared_ptr. Eventually you will still need to register your argument type though.