Qt sends signals and metadata across threads

Source: Internet
Author: User
The signalsslots of Qt can be used between threads. Event loop is completed in the main thread, so when a signal is sent by a non-main thread, the corresponding slot function will be executed by the main thread. Readers familiar with multithreading should all feel that there is a subtle problem. If the function parameter of signalsslots is a defined type. For example, you have defined a Student class and a signal function.

Reprinted please indicate the source: http://blog.csdn.net/luotuo44/article/details/39395025



Qt signals/slots can be used between threads. Because the event loop is completed in the main thread, when the non-main thread sends a signal, the corresponding slot function will be executed by the main thread.



Readers familiar with multithreading should all feel that there is a subtle problem. If the function parameters of signals/slots are of a defined type. For example, you have defined a Student class, and the signal function is sendStudent (const Student & stu); the corresponding slot function is: getStudent (const Student & stu ); if the Student parameter is a temporary variable when the non-main thread uses emit to send signals (that is, it may be immediately defactored ), the temporary variable may be parsed when the main thread executes this slot function. This is equivalent to using a wild pointer.

 

The author of Qt must have thought of this.

In the connect function, we generally only use four parameters. In fact, it has five parameters, but uses the default parameters. The fifth parameter is an enumeration type Qt: ConnectionType, which has the following five types:

  • Qt: AutoConnection: if the thread sending the signal is in the same thread as the thread executing the slot function, it is equivalent to Qt: DirectConnection. If not in the same thread, it is equivalent to Qt: QueuedConnection. This is the default parameter of the connect function.
  • Qt: DirectConnection: The transmitting signal and execution slot are completed by the same thread. The slot function is executed immediately. The code after "emit signal" is executed. That is, the "emit signal" is blocked.
  • Qt: QueuedConnection: the thread that emits signals and the thread that executes the slot function are not in the same thread. At this time, the thread that emits the signal is not blocked and returns immediately. When the thread executing the slot function is scheduled by the CPU, the slot function is executed.
  • Qt: BlockingQueuedConnection: is basically the same as Qt: QueuedConnection, but the thread that emits the signal is blocked and the slot function is executed. Therefore, if this connect attribute is set, make sure that the transmit signal thread is not the thread that executes the slot function. Otherwise, a deadlock will occur.
  • Qt: UniqueConnection: unique Association. That is, the same signal and the same slot can only call connect once. It cannot be called multiple times. Note: At this time, a signal can still be associated with multiple slots.

In the above enumeration, it indicates whether the thread is in the same thread. Its judgment is also simple. the thread that executes the slot function is the thread that executes the event loop, that is, the thread that executes the QCoreApplication a (argc, argv); a.exe c () function. Generally, the main thread executes the event loop. The launch thread is the thread that calls emit.

 

From the above Association type, we can see that the author of Qt is the thread that considers the signal to be sent, not the thread that executes the slot function. So how does Qt solve the subtle problem just now? The answer is metadata. Call qregisterpolicype before connect. ("Student"); register this Student type as metadata. In this way, the problem can be avoided.

 


 

Since I didn't read the source code of Qt, I don't know how to implement it in Qt. I regard the implementation of Qt as a black box and use a document and test to make some guesses. The following is my conjecture, which is not necessarily correct.


If this problem is solved by ourselves, we can think of the method of copying a Student class internally. In this way, no matter whether the temporary Student of the launch thread is parsed or not.

By reading the qregisterpolicype entry of the Qt assistant, you can see that it is conditional to register a type as metadata. The default constructor, copy constructor, and destructor of the public attribute must be provided for this type. This should be to copy a Student. Haha. The following is an example.

Header file:

# Ifndef TK_HPP # define TK_HPP # include
 
  
# Include
  
   
# Include
   
    
Class Student {public: Student () {} Student (const QString & name, const QString & id): m_name (name), m_id (id) {} Student (const Student & stu) {// assign a value as intended. It means that Qt cannot be copied and constructed correctly. Haha !!! M_name = "xxxx";} QString name () const {return m_name;} void name (const QString & name) {m_name = name;} private: QString m_name; QString m_id;}; class Test: public QObject {Q_OBJECTpublic: Test () {qregister1_ype
    
     
("Student"); connect (this, SIGNAL (sendStu (Student), this, SLOT (getStu (Student); //, Qt: QueuedConnection );} private slots: void getStu (const Student & stu) {qDebug () <
     
      
PrintStu (stu); stu. name ("bbb"); qDebug () <"I have reset student name \ n";} private: Test * m_test ;}; # endif // TK_HPP
     
    
   
  
 

Source File:

#include 
 
  #include"tk.hpp"int main(int argc, char *argv[]){    QCoreApplication a(argc, argv);    Test test;    MyThread mythread(&test);    mythread.start();    return a.exec();}
 

The execution output is:


We can see that Qt is indeed a replication error.



If you delete the copy constructor in Student, the output will be:


We can see that a Student has been copied inside Qt, so even if the name of Student is modified by the thread, it will not be affected.


If you delete qregisterpolicype in the Test constructor ("Student "). The following error occurs during running:



It is estimated that Qt will determine in the emit implementation whether the thread sending the signal is the main thread. If not, check whether the parameters of signals/slots are metadata. If not, the system rejects sending signals. Non-metadata is insecure.

For basic types of C/C ++ and classes defined by Qt, you do not need to register them as metadata manually. Qt has helped us with these tasks.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.