我正在使用QT 4.3.1(传统代码必须使用它),我使用信号和插槽在工作线程和GUI线程之间传递类引用。
如果QT由本机类型(Qstring,int,unsigned char)组成,或者我是否还需要QMutex,QT是否会对此类执行原子操作?在线程之间传递类或数据缓冲区的引用是否安全,或者是否有更好的方法来共享它并阻止并发访问?
我有类,COMinfo由另一个类和一个使用本机类型的结构构成:
typedef struct Port_Check_Struct
{
U_BYTE command :4;
U_BYTE spare15_4 :2; /* spare bits */
U_BYTE status :2;
} PORT_CHECK_STRUCT;
class PortInfo
{
public:
PortInfo();
QString portName;
U_BYTE Dir;
UNSIGNED16 Addr;
U_BYTE Size;
bool active;
U_BYTE lastused;
U_BYTE currused;
U_BYTE errorCntr;
U_BYTE portBuff[100];
U_BYTE dataBuff[100];
PORT_CHECK_STRUCT *portCheck;
};
class COMInfo
{
public:
UNSIGNED8 errorStatus;
UNSIGNED16 COMaddr;
PortInfo portInfo[4];
};
// Define Meta Types for SIGNAL/SLOT CROSS THREAD TYPES
qRegisterMetaType<COMInfo>("COMInfo");
我使用qRegisterMetaType()将数据类型注册到MOC。
我在工作线程和GUI线程之间传递引用,如下所示:
emit COM_DATA_UPDATE(COM_Info.portInfo[0].dataBuff)
QT对此引用了什么?它是浅层副本吗?需要复制构造函数吗?
信号定义为:
void COM_DATA_UPDATE(const U_BYTE* msg);
还有一个信号我传递了实际的const类引用:
void INFO_UPDATE(const COMInfo& comInfo);
答案 0 :(得分:1)
&#34;如果QT由本机类型组成,那么QT是否对该类执行原子操作&#34; - 语言是C ++,Qt只是一个库。因此,当从多个线程访问变量并且通常的C ++多线程规则及其内存模型(因为C ++ 11)适用时,Qt不会做任何魔术。然而,信号/插槽机制实现了用于线程间通信的消息传递机制:Queued connections(另请参阅thread synchronisation上的页面)将参数从一个线程传递到另一个线程复制它们。即,传递值类型(如QString,int,double)是安全的 - 接收线程将对发送线程数据的副本进行操作,并且不存在需要锁定的并发访问。 const引用传递的信号/槽参数也将被信号/槽系统复制。
但是,如果您将指针作为参数传递或包含在结构中,指针将被复制,而不是它指向的对象(在没有自定义复制ctor /的情况下)否则运算符实现。因此,访问传递的指针不是安全的,并且您需要同步机制,例如互斥锁。
在您的示例中,PORT_CHECK_STRUCT *portCheck
存在此问题(传递PortInfo对象时)以及void COM_DATA_UPDATE(const U_BYTE* msg)
。我建议通过std :: array(或std :: vector / QVector传递数据,如果你不能使用C ++ 11)。