object info added
This commit is contained in:
parent
c718d3ec12
commit
d75ed9d6de
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue