deleteLater 調用
事件發送
void QObject::deleteLater()
{QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}
- 首先該對象繼承QObject
- 調用deleteLater, 內部會發送刪除事件
QCoreApplication::postEvent(this, new QDeferredDeleteEvent())
到事件循環的隊列中 - 最終事件循環會調用 reciver->event(Qevent)
事件接收
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
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 leakdelete event;return;}QThreadData *data = locker.threadData;// if this is one of the compressible events, do compressionif (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 postEventListQScopedPointer<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 判斷 確認是是否執行延遲刪除事件
const bool allowDeferredDelete =(eventLevel > loopLevel|| (!eventLevel && loopLevel > 0)|| (event_type == QEvent::DeferredDelete&& eventLevel == loopLevel));if (!allowDeferredDelete) {// cannot send deferred deleteif (!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 lostdata->postEventList.addEvent(pe_copy);}continue;}
- 如果符合條件 調用
QCoreApplication::sendEvent(r, e);
- 不符合條件 制空當前隊列指針
const_cast<QPostEvent &>(pe).event = nullptr;
,將指針副本插入到隊列尾部 continue 跳過``(完成一次延遲刪除的機會)
最總調用event 事件:
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 filtersif (sendThroughObjectEventFilters(receiver, event)) {filtered = true;return filtered;}// deliver the eventconsumed = receiver->event(event);return consumed;
}
延遲刪除的核心(個人理解)
- 1: 就是通過記錄looplevel 和 eventlevel 然后在條件比較兩者
- 2:eventLevel 是每個事件中的一個快照相當于curentlevel, 他記錄的是當前looplevel, 而looplevel 是不斷變換的。相當于looplevel 是一個動態的全局或者靜態的變量, eventLevel 是每個事件中的一個屬性
場景1:主循環中的延遲刪除
// loopLevel = 0 (初始)
QCoreApplication::exec(); // loopLevel → 1QObject* obj = new QObject;
obj->deleteLater(); // eventLevel = 1// 事件處理時:
// eventLevel=1, loopLevel=1 → 條件3滿足 → 立即刪除
場景2:嵌套循環中的跨級刪除
// 主循環中 (loopLevel=1)
QObject* outerObj = new QObject;
outerObj->deleteLater(); // eventLevel=1QEventLoop nestedLoop;
// 進入嵌套循環 (loopLevel=2)// 處理outerObj的延遲刪除事件:
// eventLevel=1, loopLevel=2
// 1 > 2? false
// !1 && 2>0? false
// 事件非DeferredDelete → 不滿足條件 → 跳過刪除