Qt::BlockingQueuedConnection 与 QMetaCallEvent
Qt 创建连接类型如果是 Qt::BlockingQueuedConnection,即sender thread 与 receiver thread 不同,
但是要求 sender signal 与 receiver slot 执行是 不同线程间的同步行为。也即:在sender signal 发出后 sender线程 要 等待
receiver 线程的 slot 执行完后才能继续 向后执行指令。
该种方式sender与receiver的参数传递并未通过堆上内存的方式进行。而是receiver直接操作sender线程浅上的内存完成的。
因为sender线程处于同步等待状态,函数帧并未返回上一级函数调用者,因此sender的signal 函数桟帧数据处于有效状态。
又因为sender和receiver属于同一个进程,因此可以直接通过指针获取sender 线程调用栈中的内存数据。因此receiver slot执行完成后
在QMetaCallEvent对象销毁时 实质上 也没有释放堆内存的需求。而仅仅是通过父类析构函数执行了semaphore_.release() 通知
等待的sender线程 可以继续向后执行指令了。
实现方式:
QSemaphore semaphore;
{
QMutexLocker locker(signalSlotLock(receiver));
if (!c->isSingleShot && !c->receiver.loadAcquire())
continue;
QMetaCallEvent *ev = c->isSlotObject ?
new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &**semaphore**) :
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction,
sender, signal_index, argv, &**semaphore**);
QCoreApplication::postEvent(receiver, ev);
}
**semaphore.acquire();**
使用信号量在线程间进行同步,当QMetaCallEvent 在 receiver 线程EventLoop 处理完成后 会通过
void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type,
QThreadData *data)
{
...........
...........
**QScopedPointer**<QEvent> event_deleter(e); // will delete the event (with the mutex unlocked)
QCoreApplication::sendEvent(r, e); // after all that work, it's time to deliver the event.
...........
...........
}