最后调用callFunction() 或者metaCall()
void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)
{
// 这里得到的是QObject的数据,首先判断是否为阻塞设置
if (sender->d_func()->blockSig)
return;
// 得到全局链表
QConnectionList * const list = ::connectionList();
if (!list)
return;
QReadLocker locker(&list->lock);
void *empty_argv[] = { 0 };
if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
locker.unlock();
qt_signal_spy_callback_set.signal_begin_callback(sender, from_signal_index,
argv ? argv : empty_argv);
locker.relock();
}
// 在sender的哈希表中得到sender的连接
QConnectionList::Hash::const_iterator it = list->sendersHash.find(sender);
const QConnectionList::Hash::const_iterator end = list->sendersHash.constEnd();
if (it == end) {
if (qt_signal_spy_callback_set.signal_end_callback != 0) {
locker.unlock();
qt_signal_spy_callback_set.signal_end_callback(sender, from_signal_index);
locker.relock();
}
return;
}
QThread * const currentThread = QThread::currentThread();
const int currentQThreadId = currentThread ? QThreadData::get(currentThread)->id : -1;
// 记录sender连接的索引
QVarLengthArray<int> connections;
for (; it != end && it.key() == sender; ++it) {
connections.append(it.value());
// 打上使用标记,因为可能是放在队列中
list->connections[it.value()].inUse = 1;
}
for (int i = 0; i < connections.size(); ++i) {
const int at = connections.constData()[connections.size() - (i + 1)];
QConnectionList * const list = ::connectionList();
// 得到连接
QConnection &c = list->connections[at];
c.inUse = 0;
if (!c.receiver || (c.signal < from_signal_index || c.signal > to_signal_index))
continue;
// 判断是否放到队列中
// determine if this connection should be sent immediately or
// put into the event queue
if ((c.type == Qt::AutoConnection
&& (currentQThreadId != sender->d_func()->thread
|| c.receiver->d_func()->thread != sender->d_func()->thread))
|| (c.type == Qt::QueuedConnection)) {
::queued_activate(sender, c, argv);
continue;
}
// 为receiver设置当前发送者
const int method = c.method;
QObject * const previousSender = c.receiver->d_func()->currentSender;
c.receiver->d_func()->currentSender = sender;
list->lock.unlock();
if (qt_signal_spy_callback_set.slot_begin_callback != 0)
qt_signal_spy_callback_set.slot_begin_callback(c.receiver, method, argv ? argv : empty_argv);
#if defined(QT_NO_EXCEPTIONS)
c.receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
#else
try {
// 调用receiver的方法
c.receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
} catch (...) {
list->lock.lockForRead();
if (c.receiver)
c.receiver->d_func()->currentSender = previousSender;
throw;
}
#endif
if (qt_signal_spy_callback_set.slot_end_callback != 0)
qt_signal_spy_callback_set.slot_end_callback(c.receiver, method);
list->lock.lockForRead();
if (c.receiver)
c.receiver->d_func()->currentSender = previousSender;
}
if (qt_signal_spy_callback_set.signal_end_callback != 0) {
locker.unlock();
qt_signal_spy_callback_set.signal_end_callback(sender, from_signal_index);
locker.relock();
}
}
void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
{
int signal_index = signalOffset + local_signal_index;
/* 我们所做的第一件事,是快速检查一个 64 位的位蒙版 bit-mask。如果为 0,
* 我们就知道没有连接到该信号的东西,可以迅速返回,
* 这意味着,发送一个没有与槽连接的信号是相当迅速的。*/
if (!sender->d_func()->isSignalConnected(signal_index))
return; // nothing connected to these signals, and no spy
/* ... 跳过调试信息和 QML 调用,以及一些合理性检查 ... */
/* 使用互斥锁,因为 connectionList 中的所有操作都是线程安全的 */
QMutexLocker locker(signalSlotLock(sender));
/* 获取该信号的 ConnectionList。此处做了一些简化。真实的代码还为列表添加了引用计数和一些合理性检查 */
QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
const QObjectPrivate::ConnectionList *list =
&connectionLists->at(signal_index);
QObjectPrivate::Connection *c = list->first;
if (!c) continue;
// 我们需要最后一次检查,确保在信号发出的过程中添加的信号不会在本次发出过程被触发。
QObjectPrivate::Connection *last = list->last;
/* 遍历槽 */
do {
if (!c->receiver)
continue;
QObject * const receiver = c->receiver;
const bool receiverInSameThread = QThread::currentThreadId() == receiver->d_func()->threadData->threadId;
// 确定该连接应该立即发出,还是放入事件队列
if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
|| (c->connectionType == Qt::QueuedConnection)) {
/* 从根本上说,就是复制参数,发出事件 */
queued_activate(sender, signal_index, c, argv);
continue;
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
/* ... 跳过 ... */
continue;
}
/* 助手结构体,设置 sender()(并且在超出作用域之后重新设回 */
QConnectionSenderSwitcher sw;
if (receiverInSameThread)
sw.switchSender(receiver, sender, signal_index);
const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
const int method_relative = c->method_relative;
if (c->isSlotObject) {
/* ... 跳过 ... Qt5 风格的指向函数指针的连接 */
} else if (callFunction && c->method_offset metaObject()->methodOffset()) {
/* 如果存在 callFunction(指向由 moc 生成的 qt_static_metacall 的指针,
* 调用该函数。还需要检查已保存的 metodOffset 是否依旧可用
* (因为我们可能在析构函数中调用) */
locker.unlock(); // 实际调用时不能持有锁
callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv);
locker.relock();
} else {
/* 动态对象 */
const int method = method_relative + c->method_offset;
locker.unlock();
metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);
locker.relock();
}
// 检查该对象是否被槽析构
if (connectionLists->orphaned) break;
} while (c != last && (c = c->nextConnectionList) != 0);
}