深入理解QT的SIGNAL\SLOT机制(四):Connection结构
2017-12-20 10:54
351 查看
书接上文,本章讲述connection结构,这部分是信号和槽能发挥作用的核心部分,先来看两个结构体:
用一张图来表示:
在第三章的QMetaObjectPrivate::connect函数中3314行:
QObjectPrivate::get(s)->addConnection(signal_index, c.data());
我们根据s(也就是sender,本例中就是MyWidget对象),拿到s的实例,然后调用该实例的addConnection方法,将connection对象插入到connectionLists列表中。
这里详细讲解以下addConnection391~405行:
391行:我们看到在connectionLists中查找具体的信号是按照下标查找的,所以时间复杂度O(1),我们的mysignal是存储在0的位置,也就是说,每隔信号的index就是存储在connectionLists中的位置,所以QObject::connect方法中要确定每隔信号的signal_index。
392-395行:是在操作具有首尾指针的单链表。
399行:每次插入之后要清空无用的connection,以保证链表中的所有connection都是有用的。
这段代码就是去遍历connectionLists,检查每隔信号的dirty和inUse属性,dirty表示disconnected,但是connection对象还存在,所以应该删除,inUse是connect的引用计数,也就是说,如果当前connectionList对象已经不用,就要删除。如果connection的receiver不空,保留,为空,删除。
继续来看connect函数:
401行:
根据receiver拿到实体类,在拿到senders,这个senders不是发送者,是接受者的链表,是用来删除的,也就是最上面图结构的senders,一旦接受者被析构,这个接受者的链表会被依次删除。
402~405行:操作链表,不在赘述。
到此为止可以说把QObject::connect函数说完了,看明白的童鞋应该会理解我在一开始说的观察者模式了。
struct Connection { QObject *sender;//信号发起者 QObject *receiver;//信号接收者 union { StaticMetaCallFunction callFunction;//接受者的static_meatcall函数地址 QtPrivate::QSlotObjectBase *slotObj; }; Connection *nextConnectionList;//以下三个域是用于连接 Connection *next; Connection **prev; ...//省略 }; // ConnectionList is a singly-linked list struct ConnectionList { ConnectionList() : first(0), last(0) {} Connection *first; Connection *last; };
用一张图来表示:
在第三章的QMetaObjectPrivate::connect函数中3314行:
QObjectPrivate::get(s)->addConnection(signal_index, c.data());
我们根据s(也就是sender,本例中就是MyWidget对象),拿到s的实例,然后调用该实例的addConnection方法,将connection对象插入到connectionLists列表中。
这里详细讲解以下addConnection391~405行:
391行:我们看到在connectionLists中查找具体的信号是按照下标查找的,所以时间复杂度O(1),我们的mysignal是存储在0的位置,也就是说,每隔信号的index就是存储在connectionLists中的位置,所以QObject::connect方法中要确定每隔信号的signal_index。
392-395行:是在操作具有首尾指针的单链表。
399行:每次插入之后要清空无用的connection,以保证链表中的所有connection都是有用的。
void QObjectPrivate::cleanConnectionLists() { if (connectionLists->dirty && !connectionLists->inUse) { // remove broken connections for (int signal = -1; signal < connectionLists->count(); ++signal) { QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal]; // Set to the last entry in the connection list that was *not* // deleted. This is needed to update the list's last pointer // at the end of the cleanup. QObjectPrivate::Connection *last = 0; QObjectPrivate::Connection **prev = &connectionList.first; QObjectPrivate::Connection *c = *prev; while (c) { if (c->receiver) { last = c; prev = &c->nextConnectionList; c = *prev; } else { QObjectPrivate::Connection *next = c->nextConnectionList; *prev = next; c->deref(); c = next; } } // Correct the connection list's last pointer. // As conectionList.last could equal last, this could be a noop connectionList.last = last; } connectionLists->dirty = false; } }
这段代码就是去遍历connectionLists,检查每隔信号的dirty和inUse属性,dirty表示disconnected,但是connection对象还存在,所以应该删除,inUse是connect的引用计数,也就是说,如果当前connectionList对象已经不用,就要删除。如果connection的receiver不空,保留,为空,删除。
继续来看connect函数:
401行:
c->prev = &(QObjectPrivate::get(c->receiver)->senders);
根据receiver拿到实体类,在拿到senders,这个senders不是发送者,是接受者的链表,是用来删除的,也就是最上面图结构的senders,一旦接受者被析构,这个接受者的链表会被依次删除。
402~405行:操作链表,不在赘述。
到此为止可以说把QObject::connect函数说完了,看明白的童鞋应该会理解我在一开始说的观察者模式了。
相关文章推荐
- 深入理解QT的SIGNAL\SLOT机制(三):QObject::connect函数
- 深入理解QT的SIGNAL\SLOT机制(一):SIGNAL\SLOT如何使用
- 深入理解Qt多线程
- 深入理解Qt信号和槽机制、信号和槽中的Lambda表达式
- 深入理解Qt的.pro文件
- 深入理解Qt多线程
- Qt之深入理解gesture
- 【Qt开发】深入理解connect函数
- QT之深入理解QThread
- QT之深入理解QThread
- Qt深入理解信号与槽
- Qt深入理解信号与槽
- Qt深入理解信号与槽
- 深入理解Qt中各种消息框对话框的使用
- Qt深入理解信号与槽
- Qt之深入理解gesture
- 深入理解QT的SIGNAL\SLOT机制(二):QMetaObject相关知识
- Qt深入理解信号与槽
- 深入理解QT的SIGNAL\SLOT机制(五):信号的发射过程
- Qt之QThread(深入理解)