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.
Related
I tried to break down my problem to a small example. The real problem is a more complex communication:
I have a function that triggers a communication and connects and sends messages to a server. If there is an answer, the Client-class emits a signal containing the answer.
void communicate()
{
client.setUpMessage(); // the answer is emitted as a signal and
// and processed in the Slot
// 'reactToAnswer(...)'
client.sendMessage("HelloWorld");
}
void reactToAnswer(QString answer)
{
parser.parseAnswer() // an error could occur
}
What if an error is detected in the slot in which the response is processed? I would like to stop the execution of the function communicate(). This means that the function client.sendMessage("HelloWorld") should no longer be executed.
In my naivety I tried to handle the problem with exceptions:
void communicate()
{
try
{
client.setUpMessage(); // the answer is emitted as a signal and
// and processed in the Slot
// 'reactToAnswer(...)'
client.sendMessage("HelloWorld");
}
catch(myException)
{
// do something
}
void reactToAnswer(QString answer)
{
if( !parser.parseAnswer() )
{
throw myException;
}
}
This does not work, throwing an exception from a slot invoked by a qt-signal is undefined behaviour. The usual way is to reimplement QApplication::notify() resp. QCoreApplication()::notify, but this does not work for me. There is already a QApplication for the GUI and I want the communication class (QObject) to stand alone. All things should be treated within this class.
I hope I explained the problem comprehensibly. I do not want to use exceptions in any case, other ways to stop the communication are also right for me.
Thanks in advance!
I'm not sure that what you are trying to accomplish is a particularly good fit for the signals-and-slots paradigm... perhaps you want to go with just a regular old function call instead? i.e. something like:
void communicate()
{
QString theAnswer; // will be written to by setupMessage() unless error occurs
if (client.setUpMessage(theAnswer))
{
reactToAnswer(theAnswer);
client.sendMessage("HelloWorld");
}
}
The reason that signals-and-slots aren't a good fit is that signals are designed to be connectable to multiple slots at once, and the order in which the slots-methods are called is undefined -- so if a slot-method tries to interfere with the signal-emitting process in the way you describe, the behavior is rather unpredictable (because you don't know how many other connected slot-methods, if any, had already been called as part of the signal-emission, before your particular slot-method hit the brakes). And of course if you ever go to queued/asynchronous signals, then it won't work at all, because the slot will be called in a different context entirely, long after the signal-emitting function has already returned.
That said, if you absolutely must use signals-and-slots for this, you can have your slot emit its own error-has-occurred signal, which can be connected back to a slot in the original signal-emitting class. That slot could then set a boolean (or whatever), and your communicate() method could then check the state of that boolean (right after client.setUpMessage() has returned) to decide whether or not to continue executing or return early.
(I don't recommend that though -- signals-and-slots are there to make your program less complicated, and in this case I think using them instead of a regular function call actually makes your program more complicated, with no corresponding benefit)
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.
I am using Qt and wish to write a class that will perform some network-type operations, similar to FTP/HTTP. The class needs to connect to lots of machines, one after the other but I need the applications UI to stay (relatively) responsive during this process, so the user can cancel the operation, exit the application, etc. My first thought was to use a separate thread for network stuff but the built-in Qt FTP/HTTP (and other) classes apparently avoid using threads and instead rely on signals and slots. So, I'd like to do something similar and was hoping I could do something like this:
class Foo : public QObject
{
Q_OBJECT
public:
void start();
signals:
void next();
private slots:
void nextJob();
};
void Foo::start()
{
...
connect(this, SIGNAL(next()), this, SLOT(nextJob()));
emit next();
}
void Foo::nextJob()
{
// Process next 'chunk'
if (workLeftToDo)
{
emit next();
}
}
void Bar::StartOperation()
{
Foo* foo = new Foo;
foo->start();
}
However, this doesn't work and UI freezes until all operations have completed. I was hoping that emitting signals wouldn't actually call the slots immediately but would somehow be queued up by Qt, allowing the main UI to still operate.
So what do I need to do in order to make this work? How does Qt achieve this with the multitude of built-in classes that appear to perform lengthy tasks on a single thread?
If you're doing a length job in the UI thread the UI is going to freeze. One way to avoid this is to call once in a while QCoreApplication::processEvents().
You should be VERY careful however to understand what this does before you decide to do it. Calling this function means that a GUI event can fire in the middle of your operation. If this event can in turn create some more jobs you can end up starting a new job while in the middle of the old job.
I wouldn't be so quick dismissing the worker thread approach. It has the advantage of completely separating the work from the GUI so you are certain that something that began is going to finish.
You should also consider that Windows especially sometimes introduces non trivial delays to GUI loops. If the host is somewhat busy or in a memory thrashing state you'll find that GUI events may take up to several long seconds to finish and return control to your processing.
Use QThread with a run method like this:
void run(){ exec(); }
this will provide another execution loop, where you can do your "hard work" without acutally freezing the UI.
Note: Make sure to actually use the thread's execution loop by adding
moveToThread(this);
at the end of the Constructor of your QThread derived Thread class (the doc doesn't say much about it)
I have found that boost::signals2 uses sort of a lazy deletion of connected slots, which makes it difficult to use connections as something that manages lifetimes of objects. I am looking for a way to force slots to be deleted directly when disconnected. Any ideas on how to work around the problem by designing my code differently are also appreciated!
This is my scenario: I have a Command class responsible for doing something that takes time asynchronously, looking something like this (simplified):
class ActualWorker {
public:
boost::signals2<void ()> OnWorkComplete;
};
class Command : boost::enable_shared_from_this<Command> {
public:
...
void Execute() {
m_WorkerConnection = m_MyWorker.OnWorkDone.connect(boost::bind(&Command::Handle_OnWorkComplete, shared_from_this());
// launch asynchronous work here and return
}
boost::signals2<void ()> OnComplete;
private:
void Handle_OnWorkComplete() {
// get a shared_ptr to ourselves to make sure that we live through
// this function but don't keep ourselves alive if an exception occurs.
shared_ptr<Command> me = shared_from_this();
// Disconnect from the signal, ideally deleting the slot object
m_WorkerConnection.disconnect();
OnComplete();
// the shared_ptr now goes out of scope, ideally deleting this
}
ActualWorker m_MyWorker;
boost::signals2::connection m_WorkerConnection;
};
The class is invoked about like this:
...
boost::shared_ptr<Command> cmd(new Command);
cmd->OnComplete.connect( foo );
cmd->Execute();
// now go do something else, forget all about the cmd variable etcetera.
the Command class keeps itself alive by getting a shared_ptr to itself which is bound to the ActualWorker signal using boost::bind.
When the worker completes, the handler in Command is invoked. Now, since I would like the Command object to be destroyed, I disconnect from the signal as can be seen in the code above. The problem is that the actual slot object is not deleted when disconnected, it is only marked as invalid and then deleted at a later time. This in turn appears to depend on the signal to fire again, which it doesn't do in my case, leading to the slot never expiring. The boost::bind object thus never goes out of scope, holding a shared_ptr to my object that will never get deleted.
I can work around this by binding using the this pointer instead of a shared_ptr and then keeping my object alive using a member shared_ptr which I then release in the handler function, but it kind of makes the design feel a bit overcomplicated. Is there a way to force signals2 to delete the slot when disconnecting? Or is there something else I could do to simplify the design?
Any comments are appreciated!
boost::signals2 does clean up the slots during connect/invoke.
So if all the slots disconnect themselves from the signal, invoking the signal a second time will not call anything but it should clean up the slots.
To answer your comment, yes, invoking the signal again is not safe if there are be other slots connected, as they will be invoked again. In that case I suggest you go the other way around and connect a dummy slot, then disconnect it when your "real" slot is invoked. Connecting another slot will clean up stale connections, so your slot should be released.
Just make sure that you don't keep any references that need freeing in the dummy slot, or you're back where you started.
This is an incredibly annoying aspect of boost::signals2.
The approach I took to resolve it is to store the signal in a scoped_ptr, and when I want to force disconnection of all slots, I delete the signal. This only works in cases when you want to forcefully disconnect all connections to a signal.
Is the behaviour any more strict with a scoped_connection?
So, rather than:
void Execute() {
m_WorkerConnection = m_MyWorker.OnWorkDone.connect(boost::bind
(&Command::Handle_OnWorkComplete, shared_from_this());
// launch asynchronous work here and return
}
...
boost::signals2::connection m_WorkerConnection;
Instead using:
void Execute() {
boost::signals2::scoped_connection m_WorkerConnection
(m_MyWorker.OnWorkDone.connect(boost::bind
(&Command::Handle_OnWorkComplete, shared_from_this()));
// launch asynchronous work here and return
} // connection falls out of scope
(copy-constructed from a boost::signals2::connection)
I've not used any sort of signalling so it's more of a guess than anything else, but following Execute() you wouldn't need to disconnect(), since scoped_connection handles it for you. That's more of a 'simplify the design' rather than actually solving your problem. But it may mean that you can Execute() and then immediately ~Command() (or delete the shared_ptr).
Hope that helps.
EDIT: And by Execute() then immediately ~Command() I obviously mean from outside your Command object. When you construct the Command to execute it, you should then be able to say:
cmd->Execute();
delete cmd;
Or similar.
I ended up doing my own (subset) implementation of a signal, the main requirement being that a slot should be destroyed by a call to connection::disconnect().
The implementation goes along the lines of the signal storing all slots in a map from slot implementation pointer to a shared_ptr for a slot implementation instead of a list/vector, thereby giving quick access to individual slots without having to iterate over all slots. A slot implementation is in my case basically a boost::function.
Connections have a weak_ptr to the internal implementation class for the signal and a weak_ptr to the slot implementation type to allow the signal to go out of scope and to use the slot pointer as the key into the signal map as well as an indication on whether the connection is still active (can't use a raw pointer as that could potentially be reused).
When disconnect is called, both of these weak pointers are converted to shared_ptrs and if both of these succeed, the signal implementation is asked to disconnect the slot given by the pointer. This is done by simple erasing it from the map.
The map is protected by a mutex to allow for multithreaded use. To prevent deadlocks, the mutex is not held while calling the slots, however this means that a slot may be disconnected from a different thread just prior to being called by the signal. This is also the case with regular boost::signals2 and in both of these scenarios one needs to be able to handle a callback from a signal even after one has disconnected.
To simplify the code for when the signal is fired, I am forcing all slots to be disconnected during this. This is different from boost::signals2, that does a copy of the list of slots before calling them in order to handle disconnections/connections while firing the signal.
The above works well for my scenario, where the signal of interest is fired very seldom (and in that case only once) but there are a lot of short-lived connections that otherwise use up a lot of memory even when using the trick outlined in the question.
For other scenarios, I've been able to replace the use of a signal with just a boost::function (thus requiring that there can only be a single connection) or just by sticking with the workaround in the question where the listener itself manages its lifetime.
I stumbled upon the same problem and i really miss some kind of explicit cleanup in the API.
In my scenario i am unloading some plug-in dll's and i have to assure there are no dangling objects (slots) which refer to code (vftables or whatsoever) living in the unloaded dll. Simply disconnecting slots didn't work due to the lazy deletion stuff.
My first workaround was a signal wrapper which tweaks the disconnecting code a little bit:
template <typename Signature>
struct MySignal
{
// ...
template <typename Slot>
void disconnect (Slot&& s)
{
mPrivate.disconnect (forward (s));
// connect/disconnect dummy slot to force cleanup of s
mPrivate.connect (&MySignal::foo);
mPrivate.disconnect (&MySignal::foo);
}
private:
// dummy slot function with matching signature
// ... foo (...)
private:
::boost::signals2::signal<Signature> mPrivate;
};
Unfortunately this didn't work because connect() only does some cleanup. It doesn't guarantee cleanup of all unconnected slots. Signal invocation on the other hand does a full cleanup but a dummy invocation would also be an unacceptable behavioral change (as already mentioned by others).
In the absence of alternatives i ended up in patching the original signal class (Edit: i really would appreciate a built-in solution. this patch was my last resort). My patch is around 10 lines of code and adds a public cleanup_connections() method to signal. My signal wrapper invokes the cleanup at the end of the disconnecting methods. This approach solved my problems and i didn't encounter any performance problems so far.
Edit: Here is my patch for boost 1.5.3
Index: signals2/detail/signal_template.hpp
===================================================================
--- signals2/detail/signal_template.hpp
+++ signals2/detail/signal_template.hpp
## -220,6 +220,15 ##
typedef mpl::bool_<(is_convertible<T, group_type>::value)> is_group;
do_disconnect(slot, is_group());
}
+ void cleanup_connections () const
+ {
+ unique_lock<mutex_type> list_lock(_mutex);
+ if(_shared_state.unique() == false)
+ {
+ _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
+ }
+ nolock_cleanup_connections_from(false, _shared_state->connection_bodies().begin());
+ }
// emit signal
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
## -690,6 +699,10 ##
{
(*_pimpl).disconnect(slot);
}
+ void cleanup_connections ()
+ {
+ (*_pimpl).cleanup_connections();
+ }
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
I have my main form made Qt Designer and inheriting from QMainWindow and the UI. I need to have other threads running, and I need those threads to change things on the main form, eg progress bars, LCDs.
How do I give the other thread access to the widgets on the main form?
Thanks for any help.
Using signal/slots.
Trolltech introduces from 4.x a threadsafe mechanism for signaling using for example the
Qt::BlockingQueuedConnection parameter in connect() function.
For more details see:
http://lists.trolltech.com/qt-interest/2007-03/thread00260-0.html
As Flavius Suciu has mentioned, you can use a cross-thread signal/slot connection. They can also carry arguments, however, if you don't pass just fundamental types or Qt types as signal parameters but, say, your own custom struct, you need to tell Qt about them this way:
namespace MyNamespace { // if any...
struct MyClass { /* ... */ };
} // if any
Q_DECLARE_METATYPE( MyNamespace::MyClass )
This allows MyClass to be stuffed into QVariants, which is what Qt uses internally to ship copies of the signal arguments over thread boundaries.
You might also need to call
qRegisterMetaType<MyNamespace::MyClass>();
somewhere it's bound to be executed before any signal/slot cross-thread connection is attempted (e.g. in main(), or your QThread subclass constructor).
See the docs of Q_DECLARE_METATYPE