是否保证在QObject :: disconnect()之后没有信号从不同的线程传递?

时间:2013-05-16 22:00:20

标签: qt thread-safety signals-slots

我没有想到在disconnect()之后仍然在接收线程中传递排队信号的问题,而是:

考虑一个Sender对象在线程1中生成信号并且线程2中有一个Receiver对象的情况,其中有一个插槽通过Sender的信号连接到一个Qt::DirectConnection

现在,在Receiver::~Receiver()中,我需要确保在对象已经(可能部分)被破坏时仍然没有传递任何信号。因为连接是直接的,所以可以在线程1中随时调用该槽,尤其可以在销毁Receiver的特定属性和销毁基础QObject之间发生,这也将断开信号。所以,我的问题归结为:

在销毁Sender对象之前断开线程2中的ReceiverReceiver对象是否足够,或者我是否需要确保在线程1中没有发出信号disconnect()来电?disconnect()

我正在考虑线程1处于发出信号的中间的情况,例如在执行接收时隙的顶部并且在该时刻,在线程2中,disconnect()呼叫完成。如果{{1}}等待(通过互斥锁)线程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));