deleteLater 调用
事件发送
cpp
void QObject::deleteLater()
{
QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}
- 首先该对象继承QObject
- 调用deleteLater, 内部会发送删除事件
QCoreApplication::postEvent(this, new QDeferredDeleteEvent())
到事件循环的队列中 - 最终事件循环会调用 reciver->event(Qevent)
事件接收
cpp
bool QObject::event(QEvent *e)
{
switch (e->type()) {
case QEvent::Timer:
timerEvent((QTimerEvent*)e);
break;
case QEvent::ChildAdded:
case QEvent::ChildPolished:
case QEvent::ChildRemoved:
childEvent((QChildEvent*)e);
break;
case QEvent::DeferredDelete:
qDeleteInEventHandler(this);
break;
...
return true;
}
void qDeleteInEventHandler(QObject *o)
{
delete o;
}
- event(QEvent *e) 通过事件类型判断,是否为
延迟删除类型:QEvent::DeferredDelete
- 如果是延迟删除类型,则会调用
qDeleteInEventHandler
事件发送实现
设置删除事件的 looplevel 和 eventLevel
cpp
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type());
if (receiver == nullptr) {
qWarning("QCoreApplication::postEvent: Unexpected null receiver");
delete event;
return;
}
auto locker = QCoreApplicationPrivate::lockThreadPostEventList(receiver);
if (!locker.threadData) {
// posting during destruction? just delete the event to prevent a leak
delete event;
return;
}
QThreadData *data = locker.threadData;
// if this is one of the compressible events, do compression
if (receiver->d_func()->postedEvents
&& self && self->compressEvent(event, receiver, &data->postEventList)) {
Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event);
return;
}
if (event->type() == QEvent::DeferredDelete)
receiver->d_ptr->deleteLaterCalled = true;
if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
// remember the current running eventloop for DeferredDelete
// events posted in the receiver's thread.
// Events sent by non-Qt event handlers (such as glib) may not
// have the scopeLevel set correctly. The scope level makes sure that
// code like this:
// foo->deleteLater();
// qApp->processEvents(); // without passing QEvent::DeferredDelete
// will not cause "foo" to be deleted before returning to the event loop.
// If the scope level is 0 while loopLevel != 0, we are called from a
// non-conformant code path, and our best guess is that the scope level
// should be 1. (Loop level 0 is special: it means that no event loops
// are running.)
int loopLevel = data->loopLevel;
int scopeLevel = data->scopeLevel;
if (scopeLevel == 0 && loopLevel != 0)
scopeLevel = 1;
static_cast<QDeferredDeleteEvent *>(event)->level = loopLevel + scopeLevel;
}
// delete the event on exceptions to protect against memory leaks till the event is
// properly owned in the postEventList
QScopedPointer<QEvent> eventDeleter(event);
Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
data->postEventList.addEvent(QPostEvent(receiver, event, priority));
eventDeleter.take();
event->posted = true;
++receiver->d_func()->postedEvents;
data->canWait = false;
locker.unlock();
QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
if (dispatcher)
dispatcher->wakeUp();
}
通过looplevel 和 eventLevel 判断 确认是是否执行延迟删除事件
cpp
const bool allowDeferredDelete =
(eventLevel > loopLevel
|| (!eventLevel && loopLevel > 0)
|| (event_type == QEvent::DeferredDelete
&& eventLevel == loopLevel));
if (!allowDeferredDelete) {
// cannot send deferred delete
if (!event_type && !receiver) {
// we must copy it first; we want to re-post the event
// with the event pointer intact, but we can't delay
// nulling the event ptr until after re-posting, as
// addEvent may invalidate pe.
QPostEvent pe_copy = pe;
// null out the event so if sendPostedEvents recurses, it
// will ignore this one, as it's been re-posted.
const_cast<QPostEvent &>(pe).event = nullptr;
// re-post the copied event so it isn't lost
data->postEventList.addEvent(pe_copy);
}
continue;
}
- 如果符合条件 调用
QCoreApplication::sendEvent(r, e);
- 不符合条件 制空当前队列指针
const_cast<QPostEvent &>(pe).event = nullptr;
,将指针副本插入到队列尾部 continue 跳过``(完成一次延迟删除的机会)
最总调用event 事件:
cpp
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
// Note: when adjusting the tracepoints in here
// consider adjusting QApplicationPrivate::notify_helper too.
Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
bool consumed = false;
bool filtered = false;
Q_TRACE_EXIT(QCoreApplication_notify_exit, consumed, filtered);
// send to all application event filters (only does anything in the main thread)
if (QCoreApplication::self
&& receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
&& QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
filtered = true;
return filtered;
}
// send to all receiver event filters
if (sendThroughObjectEventFilters(receiver, event)) {
filtered = true;
return filtered;
}
// deliver the event
consumed = receiver->event(event);
return consumed;
}
延迟删除的核心(个人理解)
- 1: 就是通过记录looplevel 和 eventlevel 然后在条件比较两者
- 2:eventLevel 是每个事件中的一个快照相当于curentlevel, 他记录的是当前looplevel, 而looplevel 是不断变换的。相当于looplevel 是一个动态的全局或者静态的变量, eventLevel 是每个事件中的一个属性
场景1:主循环中的延迟删除
cpp
// loopLevel = 0 (初始)
QCoreApplication::exec(); // loopLevel → 1
QObject* obj = new QObject;
obj->deleteLater(); // eventLevel = 1
// 事件处理时:
// eventLevel=1, loopLevel=1 → 条件3满足 → 立即删除
场景2:嵌套循环中的跨级删除
cpp
// 主循环中 (loopLevel=1)
QObject* outerObj = new QObject;
outerObj->deleteLater(); // eventLevel=1
QEventLoop nestedLoop;
// 进入嵌套循环 (loopLevel=2)
// 处理outerObj的延迟删除事件:
// eventLevel=1, loopLevel=2
// 1 > 2? false
// !1 && 2>0? false
// 事件非DeferredDelete → 不满足条件 → 跳过删除