Return to site

Qt Signal Slot Thread Safety

broken image


Free Spins: Available after deposit bonus is redeemed/lost, credited as Qt Signals And Slots Thread Safe £2 bonus. MONOPOLY Live only. 1x wagering and Max bonus bet of £5 applies to winnings, 7 days to accept & Qt Signals And Slots Thread Safe 7 days to complete wagering, maximum withdrawal from winnings is £200. Qt provides thread support in the form of platform-independent threading classes, a thread-safe way of posting events, and signal-slot connections across threads. This makes it easy to develop portable multithreaded Qt applications and take advantage of multiprocessor machines. Home Articles Programming C/C.

Meeting C++
Slot

published at 20.08.2015 15:28 by Jens Weller

This is the 7th blog post in my series about writing applications with C++ using Qt and boost. This time it is about how to notify one part of our application that something has happened somewhere else. I will start with Qt, as it brings with signals and slots a mechanism to do exactly that. But, as I have the goal not to use Qt mainly in the UI Layer, I will also look on how to notify other parts of the application, when things are changing. The last episode was about QWidgets and data.

The video for this episode:

Signals and Events in Qt

But lets start with Qt. Qt offers two different systems for our needs, Qt signal/slot and QEvents. While Qt signal/slot is the moc driven signaling system of Qt (which you can connect to via QObject::connect), there is a second Event interface informing you about certain system-like events, such as QMouseEvent, QKeyEvent or QFocusEvent. Usually you have to overwrite a method to receive such events, or use an event filter, like I showed in my last post for QFocusEvents. Some classes translate QEvents to signals, such as the TreeView, which has a signal for displaying context menus. But as this blog post is more on signaling then system events..

Qt has had its own signaling mechanism for a long time now, so when you use Qt, you also will use QSignals. Qt also uses its own keywords for this: signals, slots and emit. There is an option to turn this of, and use the macros Q_SIGNAL/S,Q_SLOT/S and Q_EMIT instead: CONFIG += no_keywords. This allows to use 3rd party libraries which use these terms, e.g. boost::signal. Qt signal/slot implementation is thread safe, so that you can use it to send messages between different QThreads, this is especially important, as anything UI related should run in the main thread of Qt, anything that could block your UI should not run in this thread, so running jobs in a QThreadPool and emitting the finished result as a signal is a common pattern. Maybe I will touch this in a later post..

For now, lets see the basics of using signals and slots in Qt. This is the code from my MainWindow class constructor, connecting several signals to slots:

So, the traditional, moc driven connect method is QObject* derived sender, the SIGNAL macro defining the signal to connect to, followed by the QObject* derived receiver, then SLOT(..) is the last argument, naming the slot to connect to. There is a fifth defaultet parameter: the ConnectionType. The last line contains the new, lambda based connection option, where you again have the sender and its slot, this time as a method-pointer, and then followed by a lambda acting as the receiving slot.

This syntax can lead to a rare error, when ever a signal is overloaded, like QComboBox::currentIndexChanged, which is available with an int or QString parameter. Then you'll need an ugly static_cast to tell the compiler which version you'd like:

In this case I didn't even needed the argument from the slot. It is fairly easy to use your own signals and slots, all you need is a QObject derived class, which is processed by the moc. Mostly of course you already have classes derived from QObject indirectly, which then use signals and slots, like the page panel class:

So, slots and signals are normal member functions, declared after the qt-specific keyword signals/slots. When you want to emit a signal, its enough to just write 'emit my_signal();', and all observers on this signal will get notified. Slots are often used to react to certain events in the UI, like the currentIndexChanged signal in this case. In the widget editor of QtCreator you get an overview of available signals when right clicking and selecting 'go to slot..', this will create a slot for this signal in your QWidget derived class.

There is also the option to map certain widgets to certain values when a signal fires, this is done via QSignalMapper. I use this in a different program to have one widget for editing flag like settings, where each flag is a bit in a settings value:

The constructor only takes a QStringList for the option names, and an int for how many columns of check boxes the current use case should have. The QSignalMapper is a member variable, and each QCheckBox connects its clicked signal to the map() slot of QSignalMapper. With setMapping the connection between the sender and the value is set up. QSignalMapper offers int, QObject*, QWidget* and QString as mapping values. QVariant or a generic interface is not provided by Qt. In the clicked slot I simply toggle the bit for the corresponding flag.

When working in Qt, most of it types provide support for signals and slots through deriving from QObject, which offers connect/disconnect methods to manage your slot connections. This brings again the disadvantages of QObject and the moc, as templates can't be used in this context, all classes using signal/slot must be concrete classes. Deriving your classes from templates (CRTP e.g.) can help here to mix in a generic layer.

While Qt is fairly well prepared to manage its own messaging needs, what alternatives exist, that could be used in the non Qt related code? The C++ standard offers currently only std::function, which can be used to implement a callback mechanism. But this has its limitations, of a 1:1 or 1:many connection this is a viable option. I use it to notify my MainWindow class that a node in the tree has changed its name. Also its useful to implement classes which execute a callback in a certain context, like EventFilter in the last blog post in this series. But std::function is not an implementation of the observer pattern, and implementing your own with it would be reinventing the wheel. Boost has had for a long time a signal library, which now is available as version 2: boost::signals2.

Using boost::signals2

Honestly, if I could avoid using signals2, I would, as it has one certain disadvantage: build times increase. So far my project is kind of small, has only a few classes, which most of are less then 100 loc. Adding boost::signals2 to a class makes it hard to build a project quickly for debugging or just seeing if the work of the past hour still compiles.

The need for signals2 came in my application, when I began to understand, that there are some events, which go from the Qt layer into the boost/standard C++ layer, and then need to travel back into the Qt layer. Each Page has a shared_ptr to a layout object, which is part of a LayoutItem holding the list of layouts for a document. There is one LayoutPanel to edit, create and delete layouts in LayoutItem, and each PagePanel has a QComboBox, so that the user can select the layout for the page. Now, when a user creates/renames a layout, each PagePanel needs to be notified, but when it gets deleted, also page needs to change. This could be implemented in the Qt layer, each Qt class involved has access to the boost/C++ layer, and can make the necessary changes. But then, this important business logic of removing a layout will only work through the UI. When I use boost::signals2, it can be done in the boost/standard C++ layer.

boost::signals2 has a signal template, which has the signature as the argument, this signal type also then has the typedef for the slot type, signal::connect returns a connection object:

When ever an object subscribes to the layout signals, it must to so for all three, the vector should invoke RVO. Currently, PagePanel is the only subscriber, it simply connects to the signals using boost::bind:

Qt signal thread

One detail here is, that I do use scoped_connection, which will call disconnect() on its destruction, while the default boost::signals2::connection class does not. scoped_connection can be moved, but not copied. But once it is in the vector, it will stay there. Also, you should forward declare the connection classes, so that you don't have to include the boost/signals2.hpp headers, this prevents leaking into other sources.

But boost::signals2 can do far more. I have no use for code that depends on the order of slots called, but you can specify this with signal::contect(int group, slot):

Qt Signal Slot Thread Safety Tool

Slot

In some context it is interesting to handle the return value of a signal, for this boost::signal2 offers a combiner, which is the second template parameter to signal: signal > >. This combiner then also overwrites the return value of the signal, which is now std::vector instead of float. Another feature is that you can block a connection with shared_connection_block. Maplestory 2nd pendant slot light.

boost::signal2 is currently header only, thread safe and offers a few more customization points, for example you can change the mutex, but also the signature type, which currently is boost::function.

Alternatives to boost::signals2

If you know very well what you are doing, you could use boost::signal instead of its new version, signals2. This might improve your compile times, but boost::signals is not any more maintained. Also, while signals2 is header-only, signals is not. The thread safety is a key feature of signals2, which at some time sooner or later will come into play in your code base. I don't want to introduce a 3rd party library into my project just to have signaling/observer pattern, but you should know, that there are a few alternatives (I googled that too):

  • libsigslot
    • has open bugs from 2003 - 2011, memory leaks and other issues. But seems to do the job.
  • libsigc++
    • a standard C++ implementation, inspired by Qt, you (might) have to derive your objects from a base class. Virtual function calls are the base of this library it seems, at least for method slots, which the call has to be derived from sigc::trackable.
    • gtkmm and glibmm seem to use this for their signaling needs.
    • the 5 open bugs seem to be feature requests mostly (and nil is a keyword in Object-C, well..)
    • the library has been rewritten using modern C++ idioms (claims the site)
  • This codeproject article from 2005 gives some insights, but C++11 changes some of them I think.
  • slimsig
    • seems to be a header only alternative to boost::signals2
    • 2 open bugs, no change in one year
  • boost::synapse
    • this library is proposed for boost, but has not yet been reviewed.
    • I think it could be a more lightweight alternative to signals2
    • Currently its not threadsafe.

The only disadvantage of boost::signal2 is really its impact on compile and link time, which can be reduced through pimple and other isolation techniques, so that a recompilation is only triggered when really needed. One idea which came in my mind during this blog post is a std_signal2 header, which replaces the boost types (function, mutex etc.) with the corresponding std types. I'm not sure how this would work out, but boost::signals2 seems to be pretty well build to do this, a lot of template parameters have default values which then configure the library, and are hidden from the day to day usage.

Join the Meeting C++ patreon community!
This and other posts on Meeting C++ are enabled by my supporters on patreon!

Copyright Meetingcpp GmbH 2020 ImprintPiwik Opt outPrivacy Policy

This example was ported from the PyQt4 version by Guðjón Guðjónsson.

Introduction

In some applications it is often necessary to perform long-running tasks, such as computations or network operations, that cannot be broken up into smaller pieces and processed alongside normal application events. In such cases, we would like to be able to perform these tasks in a way that does not interfere with the normal running of the application, and ensure that the user interface continues to be updated. One way of achieving this is to perform these tasks in a separate thread to the main user interface thread, and only interact with it when we have results we need to display.

This example shows how to create a separate thread to perform a task - in this case, drawing stars for a picture - while continuing to run the main user interface thread. The worker thread draws each star onto its own individual image, and it passes each image back to the example's window which resides in the main application thread.

The User Interface

We begin by importing the modules we require. We need the math and random modules to help us draw stars.

The main window in this example is just a QWidget. We create a single Worker instance that we can reuse as required.

The user interface consists of a label, spin box and a push button that the user interacts with to configure the number of stars that the thread wil draw. The output from the thread is presented in a QLabel instance, viewer.

We connect the standard finished() and terminated() signals from the thread to the same slot in the widget. This will reset the user interface when the thread stops running. The custom output(QRect, QImage) signal is connected to the addImage() slot so that we can update the viewer label every time a new star is drawn.

The start button's clicked() signal is connected to the makePicture() slot, which is responsible for starting the worker thread.

We place each of the widgets into a grid layout and set the window's title:

Qt Signal Slot Thread Safety Pins

The makePicture() slot needs to do three things: disable the user interface widgets that are used to start a thread, clear the viewer label with a new pixmap, and start the thread with the appropriate parameters.

Since the start button is the only widget that can cause this slot to be invoked, we simply disable it before starting the thread, avoiding problems with re-entrancy.

We call a custom method in the Worker thread instance with the size of the viewer label and the number of stars, obtained from the spin box.

Whenever is star is drawn by the worker thread, it will emit a signal that is connected to the addImage() slot. This slot is called with a QRect value, indicating where the star should be placed in the pixmap held by the viewer label, and an image of the star itself:

We use a QPainter to draw the image at the appropriate place on the label's pixmap.

The updateUi() slot is called when a thread stops running. Since we usually want to let the user run the thread again, we reset the user interface to enable the start button to be pressed:

Now that we have seen how an instance of the Window class uses the worker thread, let us take a look at the thread's implementation.

The Worker Thread

The worker thread is implemented as a PyQt thread rather than a Python thread since we want to take advantage of the signals and slots mechanism to communicate with the main application.

We define size and stars attributes that store information about the work the thread is required to do, and we assign default values to them. The exiting attribute is used to tell the thread to stop processing.

Each star is drawn using a QPainterPath that we define in advance:

Before a Worker object is destroyed, we need to ensure that it stops processing. For this reason, we implement the following method in a way that indicates to the part of the object that performs the processing that it must stop, and waits until it does so.

For convenience, we define a method to set up the attributes required by the thread before starting it.

The start() method is a special method that sets up the thread and calls our implementation of the run() method. We provide the render() method instead of letting our own run() method take extra arguments because the run() method is called by PyQt itself with no arguments.

The run() method is where we perform the processing that occurs in the thread provided by the Worker instance:

Safety

published at 20.08.2015 15:28 by Jens Weller

This is the 7th blog post in my series about writing applications with C++ using Qt and boost. This time it is about how to notify one part of our application that something has happened somewhere else. I will start with Qt, as it brings with signals and slots a mechanism to do exactly that. But, as I have the goal not to use Qt mainly in the UI Layer, I will also look on how to notify other parts of the application, when things are changing. The last episode was about QWidgets and data.

The video for this episode:

Signals and Events in Qt

But lets start with Qt. Qt offers two different systems for our needs, Qt signal/slot and QEvents. While Qt signal/slot is the moc driven signaling system of Qt (which you can connect to via QObject::connect), there is a second Event interface informing you about certain system-like events, such as QMouseEvent, QKeyEvent or QFocusEvent. Usually you have to overwrite a method to receive such events, or use an event filter, like I showed in my last post for QFocusEvents. Some classes translate QEvents to signals, such as the TreeView, which has a signal for displaying context menus. But as this blog post is more on signaling then system events..

Qt has had its own signaling mechanism for a long time now, so when you use Qt, you also will use QSignals. Qt also uses its own keywords for this: signals, slots and emit. There is an option to turn this of, and use the macros Q_SIGNAL/S,Q_SLOT/S and Q_EMIT instead: CONFIG += no_keywords. This allows to use 3rd party libraries which use these terms, e.g. boost::signal. Qt signal/slot implementation is thread safe, so that you can use it to send messages between different QThreads, this is especially important, as anything UI related should run in the main thread of Qt, anything that could block your UI should not run in this thread, so running jobs in a QThreadPool and emitting the finished result as a signal is a common pattern. Maybe I will touch this in a later post..

For now, lets see the basics of using signals and slots in Qt. This is the code from my MainWindow class constructor, connecting several signals to slots:

So, the traditional, moc driven connect method is QObject* derived sender, the SIGNAL macro defining the signal to connect to, followed by the QObject* derived receiver, then SLOT(..) is the last argument, naming the slot to connect to. There is a fifth defaultet parameter: the ConnectionType. The last line contains the new, lambda based connection option, where you again have the sender and its slot, this time as a method-pointer, and then followed by a lambda acting as the receiving slot.

This syntax can lead to a rare error, when ever a signal is overloaded, like QComboBox::currentIndexChanged, which is available with an int or QString parameter. Then you'll need an ugly static_cast to tell the compiler which version you'd like:

In this case I didn't even needed the argument from the slot. It is fairly easy to use your own signals and slots, all you need is a QObject derived class, which is processed by the moc. Mostly of course you already have classes derived from QObject indirectly, which then use signals and slots, like the page panel class:

So, slots and signals are normal member functions, declared after the qt-specific keyword signals/slots. When you want to emit a signal, its enough to just write 'emit my_signal();', and all observers on this signal will get notified. Slots are often used to react to certain events in the UI, like the currentIndexChanged signal in this case. In the widget editor of QtCreator you get an overview of available signals when right clicking and selecting 'go to slot..', this will create a slot for this signal in your QWidget derived class.

There is also the option to map certain widgets to certain values when a signal fires, this is done via QSignalMapper. I use this in a different program to have one widget for editing flag like settings, where each flag is a bit in a settings value:

The constructor only takes a QStringList for the option names, and an int for how many columns of check boxes the current use case should have. The QSignalMapper is a member variable, and each QCheckBox connects its clicked signal to the map() slot of QSignalMapper. With setMapping the connection between the sender and the value is set up. QSignalMapper offers int, QObject*, QWidget* and QString as mapping values. QVariant or a generic interface is not provided by Qt. In the clicked slot I simply toggle the bit for the corresponding flag.

When working in Qt, most of it types provide support for signals and slots through deriving from QObject, which offers connect/disconnect methods to manage your slot connections. This brings again the disadvantages of QObject and the moc, as templates can't be used in this context, all classes using signal/slot must be concrete classes. Deriving your classes from templates (CRTP e.g.) can help here to mix in a generic layer.

While Qt is fairly well prepared to manage its own messaging needs, what alternatives exist, that could be used in the non Qt related code? The C++ standard offers currently only std::function, which can be used to implement a callback mechanism. But this has its limitations, of a 1:1 or 1:many connection this is a viable option. I use it to notify my MainWindow class that a node in the tree has changed its name. Also its useful to implement classes which execute a callback in a certain context, like EventFilter in the last blog post in this series. But std::function is not an implementation of the observer pattern, and implementing your own with it would be reinventing the wheel. Boost has had for a long time a signal library, which now is available as version 2: boost::signals2.

Using boost::signals2

Honestly, if I could avoid using signals2, I would, as it has one certain disadvantage: build times increase. So far my project is kind of small, has only a few classes, which most of are less then 100 loc. Adding boost::signals2 to a class makes it hard to build a project quickly for debugging or just seeing if the work of the past hour still compiles.

The need for signals2 came in my application, when I began to understand, that there are some events, which go from the Qt layer into the boost/standard C++ layer, and then need to travel back into the Qt layer. Each Page has a shared_ptr to a layout object, which is part of a LayoutItem holding the list of layouts for a document. There is one LayoutPanel to edit, create and delete layouts in LayoutItem, and each PagePanel has a QComboBox, so that the user can select the layout for the page. Now, when a user creates/renames a layout, each PagePanel needs to be notified, but when it gets deleted, also page needs to change. This could be implemented in the Qt layer, each Qt class involved has access to the boost/C++ layer, and can make the necessary changes. But then, this important business logic of removing a layout will only work through the UI. When I use boost::signals2, it can be done in the boost/standard C++ layer.

boost::signals2 has a signal template, which has the signature as the argument, this signal type also then has the typedef for the slot type, signal::connect returns a connection object:

When ever an object subscribes to the layout signals, it must to so for all three, the vector should invoke RVO. Currently, PagePanel is the only subscriber, it simply connects to the signals using boost::bind:

One detail here is, that I do use scoped_connection, which will call disconnect() on its destruction, while the default boost::signals2::connection class does not. scoped_connection can be moved, but not copied. But once it is in the vector, it will stay there. Also, you should forward declare the connection classes, so that you don't have to include the boost/signals2.hpp headers, this prevents leaking into other sources.

But boost::signals2 can do far more. I have no use for code that depends on the order of slots called, but you can specify this with signal::contect(int group, slot):

Qt Signal Slot Thread Safety Tool

In some context it is interesting to handle the return value of a signal, for this boost::signal2 offers a combiner, which is the second template parameter to signal: signal > >. This combiner then also overwrites the return value of the signal, which is now std::vector instead of float. Another feature is that you can block a connection with shared_connection_block. Maplestory 2nd pendant slot light.

boost::signal2 is currently header only, thread safe and offers a few more customization points, for example you can change the mutex, but also the signature type, which currently is boost::function.

Alternatives to boost::signals2

If you know very well what you are doing, you could use boost::signal instead of its new version, signals2. This might improve your compile times, but boost::signals is not any more maintained. Also, while signals2 is header-only, signals is not. The thread safety is a key feature of signals2, which at some time sooner or later will come into play in your code base. I don't want to introduce a 3rd party library into my project just to have signaling/observer pattern, but you should know, that there are a few alternatives (I googled that too):

  • libsigslot
    • has open bugs from 2003 - 2011, memory leaks and other issues. But seems to do the job.
  • libsigc++
    • a standard C++ implementation, inspired by Qt, you (might) have to derive your objects from a base class. Virtual function calls are the base of this library it seems, at least for method slots, which the call has to be derived from sigc::trackable.
    • gtkmm and glibmm seem to use this for their signaling needs.
    • the 5 open bugs seem to be feature requests mostly (and nil is a keyword in Object-C, well..)
    • the library has been rewritten using modern C++ idioms (claims the site)
  • This codeproject article from 2005 gives some insights, but C++11 changes some of them I think.
  • slimsig
    • seems to be a header only alternative to boost::signals2
    • 2 open bugs, no change in one year
  • boost::synapse
    • this library is proposed for boost, but has not yet been reviewed.
    • I think it could be a more lightweight alternative to signals2
    • Currently its not threadsafe.

The only disadvantage of boost::signal2 is really its impact on compile and link time, which can be reduced through pimple and other isolation techniques, so that a recompilation is only triggered when really needed. One idea which came in my mind during this blog post is a std_signal2 header, which replaces the boost types (function, mutex etc.) with the corresponding std types. I'm not sure how this would work out, but boost::signals2 seems to be pretty well build to do this, a lot of template parameters have default values which then configure the library, and are hidden from the day to day usage.

Join the Meeting C++ patreon community!
This and other posts on Meeting C++ are enabled by my supporters on patreon!

Copyright Meetingcpp GmbH 2020 ImprintPiwik Opt outPrivacy Policy

This example was ported from the PyQt4 version by Guðjón Guðjónsson.

Introduction

In some applications it is often necessary to perform long-running tasks, such as computations or network operations, that cannot be broken up into smaller pieces and processed alongside normal application events. In such cases, we would like to be able to perform these tasks in a way that does not interfere with the normal running of the application, and ensure that the user interface continues to be updated. One way of achieving this is to perform these tasks in a separate thread to the main user interface thread, and only interact with it when we have results we need to display.

This example shows how to create a separate thread to perform a task - in this case, drawing stars for a picture - while continuing to run the main user interface thread. The worker thread draws each star onto its own individual image, and it passes each image back to the example's window which resides in the main application thread.

The User Interface

We begin by importing the modules we require. We need the math and random modules to help us draw stars.

The main window in this example is just a QWidget. We create a single Worker instance that we can reuse as required.

The user interface consists of a label, spin box and a push button that the user interacts with to configure the number of stars that the thread wil draw. The output from the thread is presented in a QLabel instance, viewer.

We connect the standard finished() and terminated() signals from the thread to the same slot in the widget. This will reset the user interface when the thread stops running. The custom output(QRect, QImage) signal is connected to the addImage() slot so that we can update the viewer label every time a new star is drawn.

The start button's clicked() signal is connected to the makePicture() slot, which is responsible for starting the worker thread.

We place each of the widgets into a grid layout and set the window's title:

Qt Signal Slot Thread Safety Pins

The makePicture() slot needs to do three things: disable the user interface widgets that are used to start a thread, clear the viewer label with a new pixmap, and start the thread with the appropriate parameters.

Since the start button is the only widget that can cause this slot to be invoked, we simply disable it before starting the thread, avoiding problems with re-entrancy.

We call a custom method in the Worker thread instance with the size of the viewer label and the number of stars, obtained from the spin box.

Whenever is star is drawn by the worker thread, it will emit a signal that is connected to the addImage() slot. This slot is called with a QRect value, indicating where the star should be placed in the pixmap held by the viewer label, and an image of the star itself:

We use a QPainter to draw the image at the appropriate place on the label's pixmap.

The updateUi() slot is called when a thread stops running. Since we usually want to let the user run the thread again, we reset the user interface to enable the start button to be pressed:

Now that we have seen how an instance of the Window class uses the worker thread, let us take a look at the thread's implementation.

The Worker Thread

The worker thread is implemented as a PyQt thread rather than a Python thread since we want to take advantage of the signals and slots mechanism to communicate with the main application.

We define size and stars attributes that store information about the work the thread is required to do, and we assign default values to them. The exiting attribute is used to tell the thread to stop processing.

Each star is drawn using a QPainterPath that we define in advance:

Before a Worker object is destroyed, we need to ensure that it stops processing. For this reason, we implement the following method in a way that indicates to the part of the object that performs the processing that it must stop, and waits until it does so.

For convenience, we define a method to set up the attributes required by the thread before starting it.

The start() method is a special method that sets up the thread and calls our implementation of the run() method. We provide the render() method instead of letting our own run() method take extra arguments because the run() method is called by PyQt itself with no arguments.

The run() method is where we perform the processing that occurs in the thread provided by the Worker instance:

Information stored as attributes in the instance determines the number of stars to be drawn and the area over which they will be distributed.

We draw the number of stars requested as long as the exiting attribute remains False. This additional check allows us to terminate the thread on demand by setting the exiting attribute to True at any time.

The drawing code is not particularly relevant to this example. We simply draw on an appropriately-sized transparent image.

For each star drawn, we send the main thread information about where it should be placed along with the star's image by emitting our custom output() signal:

Since QRect and QImage objects can be serialized for transmission via the signals and slots mechanism, they can be sent between threads in this way, making it convenient to use threads in a wide range of situations where built-in types are used.

Running the Example

We only need one more piece of code to complete the example:





broken image