本文主要对我翻译的那篇博文中关于connection的建立过程做一些补充说明(那篇博文在这儿:http://blog.csdn.net/newthinker_wei/article/details/22785763)。
下面先看几个重要的成员变量和几个数据类型(类或结构体)的定义。
class Q_CORE_EXPORT QObjectPrivate : public QObjectData { ...... ...... // QObjectPrivate中的几个结构体类型的定义: struct Connection { QObject *sender; QObject *receiver; ...... ...... // The next pointer for the singly-linked ConnectionList Connection *nextConnectionList; //senders linked list Connection *next; Connection **prev; ...... ...... ushort method_offset; ushort method_relative; uint signal_index : 27; // In signal range (see QObjectPrivate::signalIndex()) ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking ushort isSlotObject : 1; ushort ownArgumentTypes : 1; ...... int method() const { return method_offset + method_relative; } ...... }; // ConnectionList is a singly-linked list struct ConnectionList { ConnectionList() : first(0), last(0) {} Connection *first; Connection *last; }; struct Sender { QObject *sender; int signal; int ref; }; ...... ...... // QObjectPrivate中的几个重要成员变量的定义: QObjectConnectionListVector *connectionLists; // QObjectConnectionListVector的定义在下一段代码中给出。 // QObjectConnectionListVector是以QObjectPrivate::ConnectionList为基础类型的 // Vector容器。每一个ConnectionList有一个first和一个last指针。 /* This vector contains the all connections from an object. Each object may have one vector containing the lists of connections for a given signal. The index in the vector correspond to the signal index. The signal index is the one returned by QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal). Negative index means connections to all signals. This vector is protected by the object mutex (signalSlotMutexes()) Each Connection is also part of a ‘senders‘ linked list. The mutex of the receiver must be locked when touching the pointers of this linked list. */ Connection *senders; // linked list of connections connected to this object Sender *currentSender; // object currently activating the object ...... ...... };
QObjectConnectionListVector的定义:
class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList> { public: bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet int inUse; //number of functions that are currently accessing this object or its connections QObjectPrivate::ConnectionList allsignals; QObjectConnectionListVector() : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0) { } QObjectPrivate::ConnectionList &operator[](int at) { if (at < 0) return allsignals; return QVector<QObjectPrivate::ConnectionList>::operator[](at); } };
可见QObjectConnectionListVector是从QVector模板类继承而来。这里不再贴出QVector的定义,只给出QtAssistant中对QVector模板类的介绍:
The QVector class is a templateclass that provides a dynamic array.
QVector<T> is one of Qt‘sgeneric containerclasses. It stores its items in adjacent(相邻的)memory locations and provides fast index-based access.
看了上面几个定义,现在可以了解connect和disconnect的过程了。
每个QObject对象都有一个QObjectConnectionListVector结构,这是一个Vector容器,它里面的基本单元都是ConnectionList类型的数据,ConnectionList的个数与该QObject对象的signal个数相同。每个ConnectionList对应一个信号,它记录了连接到这个信号上的所有连接。前面已经看到ConnectionList的定义中有两个重要成员:first和last,他们都是Connection 类型的指针,分别指向连接到这个信号上的第一个和最后一个连接。所有连接到这个信号上的连接以单向链表的方式组织了起来,Connection结构体中的nextConnectionList成员就是用来指向这个链表中的下一个连接的。
同时,每个QObject对象还有一个senders成员,senders是一个Connection类型的指针,senders本身也是一个链表的头结点,这个链表中的所有结点都是连接到这个QObject对象上的某个槽的连接。不过这个链表跟上一段提到的链表可不是同一个!虽然他们可能有一些共同结点!下面详细说明。
每一个Connection对象都同时处于两个链表当中。其中一个是以Connection的nextConnectionList成员组织起来的单向链表,这个单项链表中每个结点的共同点是,他们都依赖于同一个QObject对象的同一个信号,这个链表的头结点就是这个信号对应的ConnectionList结构中的first;另一个链表是以Connection的next和prev成员组织起来的双向链表,这个双向链表中每个结点的共同点是,他们的槽都在同一个QObject对象上,这个链表的头结点就是这个Qobject对象的sender。这两个链表会有交叉(共同结点),但他们有不同的链接指针,所以不是同一个链表。
知道了这些,再来理解connect和disconnect就容易了。Connect的时候,就是先new一个Connection对象出来,设置好这个连接的信息后,将它分别添加到上面提到的两个链表中;disconnect的时候,就从从这两个链表中将它移除,然后delete掉。而当一个QObject对象被销毁的时候,它的sender指针指向的那个双向链表中的所有连接都会被逐个移除!
*******************************************************
讨论一下另一个不相关的问题:
写到这里正好附加一段说明。不知道有没有朋友注意到,我们在Qt开发过程中经常用到的connect函数,它的返回类型也是Connection。但是,那个Connection是QMetaObject命名域中的Connection类,而不是我们上面一直讨论的QObjectPravite命名域中的那个。那QMetaObject:: Connection类中包含哪些信息呢?它跟QObjectPravite::Connection又有何关系?
下面看QMetaObject::Connection的定义。可以看出,QMetaObject::Connection的第一个成员d_ptr就是一个QObjectPravite::Connection指针,所以QMetaObject::Connection已经包含了QObjectPravite::Connection类中的所有特性。
class Q_CORE_EXPORT QMetaObject::Connection { void *d_ptr; //QObjectPrivate::Connection* explicit Connection(void *data) : d_ptr(data) { } friend class QObject; friend class QObjectPrivate; friend struct QMetaObject; public: ~Connection(); Connection(); Connection(const Connection &other); Connection &operator=(const Connection &other); #ifdef Q_QDOC operator bool() const; #else typedef void *Connection::*RestrictedBool; operator RestrictedBool() const { return d_ptr ? &Connection::d_ptr : 0; } #endif #ifdef Q_COMPILER_RVALUE_REFS inline Connection(Connection &&o) : d_ptr(o.d_ptr) { o.d_ptr = 0; } inline Connection &operator=(Connection &&other) { qSwap(d_ptr, other.d_ptr); return *this; } #endif };
关于Qt中信号和槽的Connection,布布扣,bubuko.com
原文:http://blog.csdn.net/newthinker_wei/article/details/22791617