Results 1 to 8 of 8

Thread: signal/slots across threads in Qt4

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jul 2006
    Posts
    3
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default signal/slots across threads in Qt4

    Hello,

    Qt4 claims to have a thread safe way of emitting signals between threads. Many of Qt4's slots have Qt4 data types in their signature. The copy constructors of these types are reentrant but not thread safe. However this problem is avoided since most of the time const references are used as slot arguments e.g. void mySlot(QString const& arg). That means that the slot gets the address of the data but cannot modify these data. Okay! But what about the thread that emitted the signal. I see trouble when in the emitting thread the QString goes out of scope or is modified before the slot dealt with the QString. What stunned me was that my program nevertheless crashed when I used in the emitting thread a const QString that did not went out of scope!! When I wrote similar code for a slot with an integer argument the program did not crash. My conclusions: 1. Qt4 is doing something dirty when queing a signal to the receivers event loop. 2. Qt4's signal/slot mechanism across threads is NOT THREAD SAFE.

    I include my code which I have build using the Visual Studio .NET 2003 compiler on a Windows XP-system.
    Can anybody either confirm my observations/conclusions or state whether I did some wrong coding?
    Thanks in advance!

    Qt Code:
    1. // FILE 1: receiver.h
    2. #ifndef __RECEIVER__H__
    3. #define __RECEIVER__H__
    4. #include <QtCore>
    5.  
    6.  
    7.  
    8. class Receiver : public QObject
    9. {
    10. Q_OBJECT
    11. public:
    12. Receiver(QObject *parent = 0) : QObject(parent)
    13. {
    14. }
    15. public slots:
    16. void mySlot(QString const& paS);
    17. void myIntegerSlot(int paI);
    18. };
    19.  
    20.  
    21.  
    22.  
    23.  
    24. #endif
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. // FILE 2 emitter.h
    2. #ifndef __EMITTER__H__
    3. #define __EMITTER__H__
    4. #include <QtCore>
    5.  
    6. class Receiver;
    7.  
    8.  
    9.  
    10. class Emitter : public QObject
    11. {
    12. Q_OBJECT
    13. public:
    14. Emitter(QObject *parent = 0) : QObject(parent)
    15. {
    16. }
    17. void emitSignal(QString const& paS);
    18. void emitIntegerSignal(int paI);
    19. signals:
    20. void newString(QString const& paS);
    21. void newInteger(int paI);
    22. };
    23.  
    24.  
    25.  
    26. class EmitterThread : public QThread
    27. {
    28. public:
    29. EmitterThread(Receiver *receiver);
    30. void run();
    31. private:
    32. Receiver *meReceiver;
    33. Emitter *meEmitter;
    34. };
    35.  
    36.  
    37. #endif
    To copy to clipboard, switch view to plain text mode 


    Qt Code:
    1. // FILE 3 receiver.cpp
    2. #include "receiver.h"
    3. #include <iostream>
    4. using namespace std;
    5.  
    6. void Receiver::mySlot(QString const& paS)
    7. {
    8. cout << paS.toStdString() << endl;
    9. }
    10.  
    11.  
    12. void Receiver::myIntegerSlot(int paI)
    13. {
    14. cout << paI << endl;
    15. }
    To copy to clipboard, switch view to plain text mode 


    Qt Code:
    1. // FILE 4: emitter.cpp
    2. #include "emitter.h"
    3. #include "receiver.h"
    4.  
    5.  
    6. #include <iostream>
    7. using namespace std;
    8.  
    9. void Emitter::emitSignal(QString const& paS)
    10. {
    11. emit newString(paS);
    12. }
    13.  
    14.  
    15. void Emitter::emitIntegerSignal(int paI)
    16. {
    17. emit newInteger(paI);
    18. }
    19.  
    20.  
    21.  
    22.  
    23. EmitterThread::EmitterThread(Receiver *receiver) : QThread(0), meReceiver(receiver)
    24. {
    25. meEmitter = new Emitter;
    26. QObject::connect(meEmitter,SIGNAL(newString(QString const&)),
    27. meReceiver,SLOT(mySlot(QString const&)),
    28. Qt::QueuedConnection);
    29. QObject::connect(meEmitter,SIGNAL(newInteger(int)),
    30. meReceiver,SLOT(myIntegerSlot(int)),
    31. Qt::QueuedConnection);
    32.  
    33. }
    34.  
    35. /* This run method crashes
    36. void EmitterThread::run()
    37. {
    38.   QString loText("");
    39.   while (true)
    40.   {
    41.   QThread::sleep(1);
    42.   meEmitter->emitSignal(loText);
    43.   loText += QString("_");
    44.   }
    45. }
    46. */
    47.  
    48.  
    49. /* This run method crashes
    50. void EmitterThread::run()
    51. {
    52.   while (true)
    53.   {
    54.   this->sleep(1);
    55.   meEmitter->emitSignal(QString("I am not thread safe"));
    56.   }
    57. }
    58. */
    59.  
    60. /* This run method crashes
    61. void EmitterThread::run()
    62. {
    63.   while (true)
    64.   {
    65.   QThread::sleep(1);
    66.   {
    67.   QString loText("I go out of scope while my colleague thread is using me!");
    68.   meEmitter->emitSignal(loText);
    69.   }
    70.   }
    71. }
    72. */
    73.  
    74. // This run method crashes
    75. void EmitterThread::run()
    76. {
    77. QString const loText("I go not out of scope and am not modified");
    78. while (true)
    79. {
    80. this->sleep(1);
    81. meEmitter->emitSignal(loText);
    82. }
    83. }
    84.  
    85.  
    86.  
    87.  
    88. /* This run method does not crash (it emits a copy of an integer)
    89. void EmitterThread::run()
    90. {
    91.   int i = 0;
    92.   while (true)
    93.   {
    94.   this->msleep(10);
    95.   meEmitter->emitIntegerSignal(i);
    96.   i++;
    97.   }
    98. }
    99. */
    To copy to clipboard, switch view to plain text mode 



    Qt Code:
    1. // FILE 5: main.cpp
    2. #include "receiver.h"
    3. #include "emitter.h"
    4.  
    5. #include <QtCore>
    6. #include <QtGui>
    7.  
    8. int main(int argc, char *argv[])
    9. {
    10. QApplication app(argc,argv);
    11. Receiver loReceiver; // lives in Main Thread
    12.  
    13. EmitterThread loET(&loReceiver);
    14. loET.start();
    15. return app.exec();
    16. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by jacek; 28th July 2006 at 10:19. Reason: added code tags

Similar Threads

  1. Threads in GUI application
    By blackliteon in forum Qt Programming
    Replies: 7
    Last Post: 14th April 2006, 09:48
  2. Threads communication
    By probine in forum Qt Programming
    Replies: 4
    Last Post: 31st March 2006, 14:46
  3. Replies: 16
    Last Post: 7th March 2006, 15:57
  4. QMessageBox and threads
    By vfernandez in forum Qt Programming
    Replies: 3
    Last Post: 5th February 2006, 17:24
  5. [QT4] threads, signals, and slots, please help.
    By ucntcme in forum Qt Programming
    Replies: 12
    Last Post: 25th January 2006, 14:23

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.