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()) {
|
if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
|
||||||
// remember the current running eventloop for DeferredDelete
|
// remember the current running eventloop for DeferredDelete
|
||||||
// events posted in the receiver's thread
|
// events posted in the receiver's thread
|
||||||
|
static_cast<QDeferredDeleteEvent *>(event)->level = data->loopLevel;
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete the event on exceptions to protect against memory leaks till the event is
|
// 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
|
// DeferredDelete events are only sent when we are explicitly asked to
|
||||||
// (s.a. QEvent::DeferredDelete), and then only if the event loop that
|
// (s.a. QEvent::DeferredDelete), and then only if the event loop that
|
||||||
// posted the event has returned.
|
// posted the event has returned.
|
||||||
|
int loopLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel();
|
||||||
const bool allowDeferredDelete =
|
const bool allowDeferredDelete =
|
||||||
(quintptr(pe.event->d) > unsigned(data->loopLevel)
|
(loopLevel > data->loopLevel
|
||||||
|| (!quintptr(pe.event->d) && data->loopLevel > 0)
|
|| (!loopLevel && data->loopLevel > 0)
|
||||||
|| (event_type == QEvent::DeferredDelete
|
|| (event_type == QEvent::DeferredDelete
|
||||||
&& quintptr(pe.event->d) == unsigned(data->loopLevel)));
|
&& loopLevel == data->loopLevel));
|
||||||
if (!allowDeferredDelete) {
|
if (!allowDeferredDelete) {
|
||||||
// cannot send deferred delete
|
// cannot send deferred delete
|
||||||
if (!event_type && !receiver) {
|
if (!event_type && !receiver) {
|
||||||
|
@ -116,7 +116,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
\value ContentsRectChange The margins of the widget's content rect changed.
|
\value ContentsRectChange The margins of the widget's content rect changed.
|
||||||
\value ContextMenu Context popup menu (QContextMenuEvent).
|
\value ContextMenu Context popup menu (QContextMenuEvent).
|
||||||
\value CursorChange The widget's cursor has changed.
|
\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 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 DragLeave The cursor leaves a widget during a drag and drop operation (QDragLeaveEvent).
|
||||||
\value DragMove A drag and drop operation is in progress (QDragMoveEvent).
|
\value DragMove A drag and drop operation is in progress (QDragMoveEvent).
|
||||||
@ -580,4 +580,24 @@ QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent()
|
|||||||
\sa QObject::setProperty(), QObject::dynamicPropertyNames()
|
\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
|
QT_END_NAMESPACE
|
||||||
|
@ -360,6 +360,17 @@ private:
|
|||||||
QByteArray n;
|
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_NAMESPACE
|
||||||
|
|
||||||
QT_END_HEADER
|
QT_END_HEADER
|
||||||
|
@ -1907,7 +1907,7 @@ void QObject::removeEventFilter(QObject *obj)
|
|||||||
*/
|
*/
|
||||||
void QObject::deleteLater()
|
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;
|
QPointer<SendPostedEventsTester> p = this;
|
||||||
QApplication::postEvent(this, new QEvent(QEvent::User));
|
QApplication::postEvent(this, new QEvent(QEvent::User));
|
||||||
// DeferredDelete should not be delivered until returning from this function
|
// DeferredDelete should not be delivered until returning from this function
|
||||||
QApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
|
QApplication::postEvent(this, new QDeferredDeleteEvent());
|
||||||
|
|
||||||
QEventLoop eventLoop;
|
QEventLoop eventLoop;
|
||||||
QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user