object info added

This commit is contained in:
Uwe Rathmann 2021-10-07 17:47:15 +02:00
parent c718d3ec12
commit d75ed9d6de
1 changed files with 98 additions and 27 deletions

View File

@ -14,6 +14,13 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qquickitem_p.h> #include <private/qquickitem_p.h>
QSK_QT_PRIVATE_END QSK_QT_PRIVATE_END
#define QSK_OBJECT_INFO 0
#if QSK_OBJECT_INFO
#include <qhash.h>
#include <qtimer.h>
#endif
static inline bool qskIsItem( const QObject* object ) static inline bool qskIsItem( const QObject* object )
{ {
QObjectPrivate* o_p = QObjectPrivate::get( const_cast< QObject* >( object ) ); QObjectPrivate* o_p = QObjectPrivate::get( const_cast< QObject* >( object ) );
@ -30,6 +37,15 @@ static inline bool qskIsItem( const QObject* object )
namespace namespace
{ {
#if QSK_OBJECT_INFO
class ObjectInfo
{
public:
QString name;
QString className;
};
#endif
class Counter class Counter
{ {
public: public:
@ -64,14 +80,36 @@ namespace
int maximum; int maximum;
}; };
class CounterData
{
public:
Counter counter[ 2 ];
#if QSK_OBJECT_INFO
void insertObjectInfo( const QObject* object )
{
objectTable.insert( object,
{ object->objectName(), object->metaObject()->className() } );
}
void removeObjectInfo( const QObject* object )
{
objectTable.remove( object );
}
QHash< const QObject*, ObjectInfo > objectTable;
#endif
};
class CounterHook class CounterHook
{ {
public: public:
CounterHook(); CounterHook();
~CounterHook(); ~CounterHook();
void registerCounters( Counter[], bool on ); void registerCounters( CounterData*, bool on );
bool isCountersRegistered( const Counter[] ) const; bool isCountersRegistered( const CounterData* ) const;
bool isActive() const; bool isActive() const;
@ -86,7 +124,7 @@ namespace
static void addObjectHook( QObject* ); static void addObjectHook( QObject* );
static void removeObjectHook( QObject* ); static void removeObjectHook( QObject* );
QSet< Counter* > m_countersSet; QSet< CounterData* > m_counterDataSet;
quintptr m_otherStartup; quintptr m_otherStartup;
quintptr m_otherAddObject; quintptr m_otherAddObject;
@ -115,22 +153,22 @@ CounterHook::~CounterHook()
qtHookData[ QHooks::RemoveQObject ] = m_otherRemoveObject; qtHookData[ QHooks::RemoveQObject ] = m_otherRemoveObject;
} }
void CounterHook::registerCounters( Counter counters[], bool on ) void CounterHook::registerCounters( CounterData* data, bool on )
{ {
if ( on ) if ( on )
m_countersSet.insert( counters ); m_counterDataSet.insert( data );
else else
m_countersSet.remove( counters ); m_counterDataSet.remove( data );
} }
bool CounterHook::isCountersRegistered( const Counter counters[] ) const bool CounterHook::isCountersRegistered( const CounterData* data ) const
{ {
return m_countersSet.contains( const_cast< Counter* >( counters ) ); return m_counterDataSet.contains( const_cast< CounterData* >( data ) );
} }
bool CounterHook::isActive() const bool CounterHook::isActive() const
{ {
return !m_countersSet.isEmpty(); return !m_counterDataSet.isEmpty();
} }
void CounterHook::startup() void CounterHook::startup()
@ -146,12 +184,20 @@ void CounterHook::addObject( QObject* object )
{ {
const bool isItem = qskIsItem( object ); const bool isItem = qskIsItem( object );
for ( auto counters : qskAsConst( m_countersSet ) ) for ( auto counterData : qskAsConst( m_counterDataSet ) )
{ {
counters[ QskObjectCounter::Objects ].increment(); counterData->counter[ QskObjectCounter::Objects ].increment();
if ( isItem ) if ( isItem )
counters[ QskObjectCounter::Items ].increment(); counterData->counter[ QskObjectCounter::Items ].increment();
#if QSK_OBJECT_INFO
{
// object is not fully constructed here
QTimer::singleShot( 0, object,
[ counterData, object ] { counterData->insertObjectInfo( object ); } );
}
#endif
} }
if ( m_otherAddObject ) if ( m_otherAddObject )
@ -162,12 +208,16 @@ void CounterHook::removeObject( QObject* object )
{ {
const bool isItem = qskIsItem( object ); const bool isItem = qskIsItem( object );
for ( auto counters : qskAsConst( m_countersSet ) ) for ( auto counterData : qskAsConst( m_counterDataSet ) )
{ {
counters[ QskObjectCounter::Objects ].decrement(); counterData->counter[ QskObjectCounter::Objects ].decrement();
if ( isItem ) if ( isItem )
counters[ QskObjectCounter::Items ].decrement(); counterData->counter[ QskObjectCounter::Items ].decrement();
#if QSK_OBJECT_INFO
counterData->removeObjectInfo( object );
#endif
} }
if ( m_otherRemoveObject ) if ( m_otherRemoveObject )
@ -219,8 +269,7 @@ class QskObjectCounter::PrivateData
{ {
} }
CounterData counterData;
Counter counter[ 2 ];
const bool debugAtDestruction; const bool debugAtDestruction;
}; };
@ -245,11 +294,11 @@ void QskObjectCounter::setActive( bool on )
if ( qskCounterHook == nullptr ) if ( qskCounterHook == nullptr )
qskCounterHook = new CounterHook(); qskCounterHook = new CounterHook();
qskCounterHook->registerCounters( m_data->counter, on ); qskCounterHook->registerCounters( &m_data->counterData, on );
} }
else else
{ {
qskCounterHook->registerCounters( m_data->counter, on ); qskCounterHook->registerCounters( &m_data->counterData, on );
if ( !qskCounterHook->isActive() ) if ( !qskCounterHook->isActive() )
{ {
if ( qskAutoDeleteHook ) if ( qskAutoDeleteHook )
@ -263,38 +312,40 @@ void QskObjectCounter::setActive( bool on )
bool QskObjectCounter::isActive() const bool QskObjectCounter::isActive() const
{ {
return qskCounterHook && qskCounterHook->isCountersRegistered( m_data->counter ); return qskCounterHook && qskCounterHook->isCountersRegistered( &m_data->counterData );
} }
void QskObjectCounter::reset() void QskObjectCounter::reset()
{ {
m_data->counter[ Objects ].reset(); auto& counters = m_data->counterData.counter;
m_data->counter[ Items ].reset();
counters[ Objects ].reset();
counters[ Items ].reset();
} }
int QskObjectCounter::created( ObjectType objectType ) const int QskObjectCounter::created( ObjectType objectType ) const
{ {
return m_data->counter[ objectType ].created; return m_data->counterData.counter[ objectType ].created;
} }
int QskObjectCounter::destroyed( ObjectType objectType ) const int QskObjectCounter::destroyed( ObjectType objectType ) const
{ {
return m_data->counter[ objectType ].destroyed; return m_data->counterData.counter[ objectType ].destroyed;
} }
int QskObjectCounter::current( ObjectType objectType ) const int QskObjectCounter::current( ObjectType objectType ) const
{ {
return m_data->counter[ objectType ].current; return m_data->counterData.counter[ objectType ].current;
} }
int QskObjectCounter::maximum( ObjectType objectType ) const int QskObjectCounter::maximum( ObjectType objectType ) const
{ {
return m_data->counter[ objectType ].maximum; return m_data->counterData.counter[ objectType ].maximum;
} }
void QskObjectCounter::debugStatistics( QDebug debug, ObjectType objectType ) const void QskObjectCounter::debugStatistics( QDebug debug, ObjectType objectType ) const
{ {
const auto& c = m_data->counter[ objectType ]; const auto& c = m_data->counterData.counter[ objectType ];
QDebugStateSaver saver( debug ); QDebugStateSaver saver( debug );
debug.nospace(); debug.nospace();
@ -304,6 +355,26 @@ void QskObjectCounter::debugStatistics( QDebug debug, ObjectType objectType ) co
<< ", current: " << c.current << ", current: " << c.current
<< ", maximum: " << c.maximum; << ", maximum: " << c.maximum;
debug << ')'; debug << ')';
#if QSK_OBJECT_INFO
if ( objectType == Objects )
{
const auto& objectTable = m_data->counterData.objectTable;
if ( !objectTable.isEmpty() )
{
debug << "\n\t=== Leaks ===\n";
for ( auto it = objectTable.constBegin(); it != objectTable.constEnd(); ++it )
{
const auto& info = it.value();
debug << "\tClass: " << info.className;
if ( !info.name.isEmpty() )
debug << " Name: " << info.name;
debug << '\n';
}
}
}
#endif
} }
void QskObjectCounter::dump() const void QskObjectCounter::dump() const