summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcore_mac_objc.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qcore_mac_objc.mm')
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm66
1 files changed, 65 insertions, 1 deletions
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index db7e55f4b1..24d73fa8be 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -84,18 +84,82 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
// -------------------------------------------------------------------------
+QT_END_NAMESPACE
+QT_USE_NAMESPACE
+@interface QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) : NSObject
+{
+ NSAutoreleasePool **m_pool;
+}
+-(id)initWithPool:(NSAutoreleasePool**)pool;
+@end
+@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker)
+-(id)initWithPool:(NSAutoreleasePool**)pool
+{
+ if (self = [super init])
+ m_pool = pool;
+ return self;
+}
+-(void)dealloc
+{
+ if (*m_pool) {
+ // The pool is still valid, which means we're not being drained from
+ // the corresponding QMacAutoReleasePool (see below).
+
+ // QMacAutoReleasePool has only a single member, the NSAutoreleasePool*
+ // so the address of that member is also the QMacAutoReleasePool itself.
+ QMacAutoReleasePool *pool = reinterpret_cast<QMacAutoReleasePool *>(m_pool);
+ qWarning() << "Premature drain of" << pool << "This can happen if you've allocated"
+ << "the pool on the heap, or as a member of a heap-allocated object. This is not a"
+ << "supported use of QMacAutoReleasePool, and might result in crashes when objects"
+ << "in the pool are deallocated and then used later on under the assumption they"
+ << "will be valid until" << pool << "has been drained.";
+
+ // Reset the pool so that it's not drained again later on
+ *m_pool = nullptr;
+ }
+
+ [super dealloc];
+}
+@end
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
+QT_BEGIN_NAMESPACE
+
QMacAutoReleasePool::QMacAutoReleasePool()
: pool([[NSAutoreleasePool alloc] init])
{
+ [[[QMacAutoReleasePoolTracker alloc] initWithPool:
+ reinterpret_cast<NSAutoreleasePool **>(&pool)] autorelease];
}
QMacAutoReleasePool::~QMacAutoReleasePool()
{
+ if (!pool) {
+ qWarning() << "Prematurely drained pool" << this << "finally drained. Any objects belonging"
+ << "to this pool have already been released, and have potentially been invalid since the"
+ << "premature drain earlier on.";
+ return;
+ }
+
+ // Save and reset pool before draining, so that the pool tracker can know
+ // that it's being drained by its owning pool.
+ NSAutoreleasePool *savedPool = static_cast<NSAutoreleasePool*>(pool);
+ pool = nullptr;
+
// Drain behaves the same as release, with the advantage that
// if we're ever used in a garbage-collected environment, the
// drain acts as a hint to the garbage collector to collect.
- [static_cast<NSAutoreleasePool*>(pool) drain];
+ [savedPool drain];
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QMacAutoReleasePool(" << (const void *)pool << ')';
+ return debug;
}
+#endif // !QT_NO_DEBUG_STREAM
#ifdef Q_OS_MACOS
/*