我没有想到在disconnect()
之后仍然在接收线程中传递排队信号的问题,而是:
考虑一个Sender
对象在线程1中生成信号并且线程2中有一个Receiver
对象的情况,其中有一个插槽通过Sender
的信号连接到一个Qt::DirectConnection
。
现在,在Receiver::~Receiver()
中,我需要确保在对象已经(可能部分)被破坏时仍然没有传递任何信号。因为连接是直接的,所以可以在线程1中随时调用该槽,尤其可以在销毁Receiver
的特定属性和销毁基础QObject
之间发生,这也将断开信号。所以,我的问题归结为:
在销毁Sender
对象之前断开线程2中的Receiver
和Receiver
对象是否足够,或者我是否需要确保在线程1中没有发出信号disconnect()
来电?disconnect()
我正在考虑线程1处于发出信号的中间的情况,例如在执行接收时隙的顶部并且在该时刻,在线程2中,disconnect()
呼叫完成。如果{{1}}等待(通过互斥锁)线程1在断开连接之前完成信号传递并阻止进一步的信号传递,一切都会好的但我不确定是不是这样。
答案 0 :(得分:4)
是disconnect()
和connect()
正在使用互斥锁进行保护。
这些是disconnect()
函数的第一行:
bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index,
DisconnectType disconnectType)
{
if (!sender)
return false;
QObject *s = const_cast<QObject *>(sender);
QMutex *senderMutex = signalSlotLock(sender);
QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
QOrderedMutexLocker locker(senderMutex, receiverMutex);
以下是connect()
函数的第一行:
bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index, int type, int *types)
{
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
如果您查看QObject
文档,则可以看到:
注意:此类中的所有函数都是可重入的,但 connect(), connect(),disconnect()和disconnect()也是线程安全的。
修改强>
当发出信号时,调用QMetaObject :: activate函数来锁定发送者的对象互斥锁:
void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
void **argv)
{
...
QMutexLocker locker(signalSlotLock(sender));