Add QDeferredDeleteEvent
Use this to store the loop-level counter needed by QCoreApplication when determining when it is safe to delete an object. This removes the hack to hijack the QEvent::d pointer (even though the pointer is unused). Change-Id: I91c0b1aa00235ec6e13feb30bf928e56d2f80026 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
00f88bd090
commit
9b07fd0d5c
@ -1105,13 +1105,7 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
|
||||
if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
|
||||
// remember the current running eventloop for DeferredDelete
|
||||
// events posted in the receiver's thread
|
||||
|
||||
// check that QEvent's d pointer is unused before we store the loop level
|
||||
// if further updates to QEvent have made the use of the d pointer necessary,
|
||||
// then update this code to store the loop level somewhere else
|
||||
Q_ASSERT_X(event->d == 0, "QCoreApplication::postEvent",
|
||||
"Internal error: this code relies on QEvent::d being null");
|
||||
event->d = reinterpret_cast<QEventPrivate *>(quintptr(data->loopLevel));
|
||||
static_cast<QDeferredDeleteEvent *>(event)->level = data->loopLevel;
|
||||
}
|
||||
|
||||
// delete the event on exceptions to protect against memory leaks till the event is
|
||||
@ -1280,11 +1274,12 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
|
||||
// DeferredDelete events are only sent when we are explicitly asked to
|
||||
// (s.a. QEvent::DeferredDelete), and then only if the event loop that
|
||||
// posted the event has returned.
|
||||
int loopLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel();
|
||||
const bool allowDeferredDelete =
|
||||
(quintptr(pe.event->d) > unsigned(data->loopLevel)
|
||||
|| (!quintptr(pe.event->d) && data->loopLevel > 0)
|
||||
(loopLevel > data->loopLevel
|
||||
|| (!loopLevel && data->loopLevel > 0)
|
||||
|| (event_type == QEvent::DeferredDelete
|
||||
&& quintptr(pe.event->d) == unsigned(data->loopLevel)));
|
||||
&& loopLevel == data->loopLevel));
|
||||
if (!allowDeferredDelete) {
|
||||
// cannot send deferred delete
|
||||
if (!event_type && !receiver) {
|
||||
|
@ -116,7 +116,7 @@ QT_BEGIN_NAMESPACE
|
||||
\value ContentsRectChange The margins of the widget's content rect changed.
|
||||
\value ContextMenu Context popup menu (QContextMenuEvent).
|
||||
\value CursorChange The widget's cursor has changed.
|
||||
\value DeferredDelete The object will be deleted after it has cleaned up.
|
||||
\value DeferredDelete The object will be deleted after it has cleaned up (QDeferredDeleteEvent).
|
||||
\value DragEnter The cursor enters a widget during a drag and drop operation (QDragEnterEvent).
|
||||
\value DragLeave The cursor leaves a widget during a drag and drop operation (QDragLeaveEvent).
|
||||
\value DragMove A drag and drop operation is in progress (QDragMoveEvent).
|
||||
@ -580,4 +580,24 @@ QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent()
|
||||
\sa QObject::setProperty(), QObject::dynamicPropertyNames()
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a deferred delete event with an initial loopLevel() of zero.
|
||||
*/
|
||||
QDeferredDeleteEvent::QDeferredDeleteEvent()
|
||||
: QEvent(QEvent::DeferredDelete)
|
||||
, level(0)
|
||||
{ }
|
||||
|
||||
/*! \internal */
|
||||
QDeferredDeleteEvent::~QDeferredDeleteEvent()
|
||||
{ }
|
||||
|
||||
/*! \fn int QDeferredDeleteEvent::loopLevel() const
|
||||
|
||||
Returns the loop-level in which the event was posted. The
|
||||
loop-level is set by QCoreApplication::postEvent().
|
||||
|
||||
\sa QObject::deleteLater()
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -360,6 +360,17 @@ private:
|
||||
QByteArray n;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QDeferredDeleteEvent : public QEvent
|
||||
{
|
||||
public:
|
||||
explicit QDeferredDeleteEvent();
|
||||
~QDeferredDeleteEvent();
|
||||
int loopLevel() const { return level; }
|
||||
private:
|
||||
int level;
|
||||
friend class QCoreApplication;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QT_END_HEADER
|
||||
|
@ -1907,7 +1907,7 @@ void QObject::removeEventFilter(QObject *obj)
|
||||
*/
|
||||
void QObject::deleteLater()
|
||||
{
|
||||
QCoreApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
|
||||
QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1045,7 +1045,7 @@ void SendPostedEventsTester::doTest()
|
||||
QPointer<SendPostedEventsTester> p = this;
|
||||
QApplication::postEvent(this, new QEvent(QEvent::User));
|
||||
// DeferredDelete should not be delivered until returning from this function
|
||||
QApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
|
||||
QApplication::postEvent(this, new QDeferredDeleteEvent());
|
||||
|
||||
QEventLoop eventLoop;
|
||||
QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
|
||||
|
Loading…
x
Reference in New Issue
Block a user