hiding code in QskObjectCounter.cpp

This commit is contained in:
Uwe Rathmann 2021-10-07 13:49:13 +02:00
parent 18dfd907fe
commit 22e75daf6a
2 changed files with 164 additions and 140 deletions

View File

@ -28,108 +28,171 @@ static inline bool qskIsItem( const QObject* object )
return dynamic_cast< QQuickItemPrivate* >( o_p ) != nullptr; return dynamic_cast< QQuickItemPrivate* >( o_p ) != nullptr;
} }
static void qskStartupHook(); namespace
static void qskAddObjectHook( QObject* );
static void qskRemoveObjectHook( QObject* );
class QskObjectCounterHook
{ {
public: class Counter
QskObjectCounterHook()
{ {
public:
Counter()
{
reset();
}
void reset()
{
created = destroyed = current = maximum = 0;
}
void increment()
{
created++;
current++;
if ( current > maximum )
maximum = current;
}
void decrement()
{
destroyed++;
current--;
}
int created;
int destroyed;
int current;
int maximum;
};
class CounterHook
{
public:
CounterHook();
~CounterHook();
void registerCounters( Counter[], bool on );
bool isCountersRegistered( const Counter[] ) const;
bool isActive() const;
void startup();
void addObject( QObject* );
void removeObject( QObject* );
static void cleanupHook();
private:
static void startupHook();
static void addObjectHook( QObject* );
static void removeObjectHook( QObject* );
QSet< Counter* > m_countersSet;
quintptr m_otherStartup;
quintptr m_otherAddObject;
quintptr m_otherRemoveObject;
};
}
static bool qskAutoDeleteHook = false;
static CounterHook* qskCounterHook = nullptr;
CounterHook::CounterHook()
{
m_otherStartup = qtHookData[ QHooks::Startup ]; m_otherStartup = qtHookData[ QHooks::Startup ];
m_otherAddObject = qtHookData[ QHooks::AddQObject ]; m_otherAddObject = qtHookData[ QHooks::AddQObject ];
m_otherRemoveObject = qtHookData[ QHooks::RemoveQObject ]; m_otherRemoveObject = qtHookData[ QHooks::RemoveQObject ];
qtHookData[ QHooks::Startup ] = reinterpret_cast< quintptr >( &qskStartupHook ); qtHookData[ QHooks::Startup ] = reinterpret_cast< quintptr >( &startupHook );
qtHookData[ QHooks::AddQObject ] = reinterpret_cast< quintptr >( &qskAddObjectHook ); qtHookData[ QHooks::AddQObject ] = reinterpret_cast< quintptr >( &addObjectHook );
qtHookData[ QHooks::RemoveQObject ] = reinterpret_cast< quintptr >( &qskRemoveObjectHook ); qtHookData[ QHooks::RemoveQObject ] = reinterpret_cast< quintptr >( &removeObjectHook );
} }
~QskObjectCounterHook() CounterHook::~CounterHook()
{ {
qtHookData[ QHooks::Startup ] = m_otherStartup; qtHookData[ QHooks::Startup ] = m_otherStartup;
qtHookData[ QHooks::AddQObject ] = m_otherAddObject; qtHookData[ QHooks::AddQObject ] = m_otherAddObject;
qtHookData[ QHooks::RemoveQObject ] = m_otherRemoveObject; qtHookData[ QHooks::RemoveQObject ] = m_otherRemoveObject;
} }
void registerCounter( QskObjectCounter* counter, bool on ) void CounterHook::registerCounters( Counter counters[], bool on )
{ {
if ( on ) if ( on )
m_counterSet.insert( counter ); m_countersSet.insert( counters );
else else
m_counterSet.remove( counter ); m_countersSet.remove( counters );
} }
bool isCounterRegistered( const QskObjectCounter* counter ) const bool CounterHook::isCountersRegistered( const Counter counters[] ) const
{ {
return m_counterSet.contains( const_cast< QskObjectCounter* >( counter ) ); return m_countersSet.contains( const_cast< Counter* >( counters ) );
} }
bool isActive() const bool CounterHook::isActive() const
{ {
return !m_counterSet.isEmpty(); return !m_countersSet.isEmpty();
} }
void startup() void CounterHook::startup()
{ {
#if 0 #if 0
qDebug() << "** QskObjectCounterHook enabled"; qDebug() << "** QskObjectCounterHook enabled";
#endif #endif
if ( m_otherStartup ) if ( m_otherStartup )
reinterpret_cast< QHooks::StartupCallback >( m_otherStartup )(); reinterpret_cast< QHooks::StartupCallback >( m_otherStartup )();
} }
void addObject( QObject* object ) void CounterHook::addObject( QObject* object )
{
const bool isItem = qskIsItem( object );
for ( auto counters : qskAsConst( m_countersSet ) )
{ {
for ( auto counter : qskAsConst( m_counterSet ) ) counters[ QskObjectCounter::Objects ].increment();
counter->addObject( object );
if ( isItem )
counters[ QskObjectCounter::Items ].increment();
}
if ( m_otherAddObject ) if ( m_otherAddObject )
reinterpret_cast< QHooks::AddQObjectCallback >( m_otherAddObject )( object ); reinterpret_cast< QHooks::AddQObjectCallback >( m_otherAddObject )( object );
} }
void removeObject( QObject* object ) void CounterHook::removeObject( QObject* object )
{
const bool isItem = qskIsItem( object );
for ( auto counters : qskAsConst( m_countersSet ) )
{ {
for ( auto counter : qskAsConst( m_counterSet ) ) counters[ QskObjectCounter::Objects ].decrement();
counter->removeObject( object );
if ( isItem )
counters[ QskObjectCounter::Items ].decrement();
}
if ( m_otherRemoveObject ) if ( m_otherRemoveObject )
reinterpret_cast< QHooks::RemoveQObjectCallback >( m_otherRemoveObject )( object ); reinterpret_cast< QHooks::RemoveQObjectCallback >( m_otherRemoveObject )( object );
} }
static bool autoDelete; void CounterHook::startupHook()
private:
QSet< QskObjectCounter* > m_counterSet;
quintptr m_otherStartup;
quintptr m_otherAddObject;
quintptr m_otherRemoveObject;
};
bool QskObjectCounterHook::autoDelete = false;
static QskObjectCounterHook* qskCounterHook = nullptr;
static void qskStartupHook()
{ {
if ( qskCounterHook ) if ( qskCounterHook )
qskCounterHook->startup(); qskCounterHook->startup();
} }
static void qskAddObjectHook( QObject* object ) void CounterHook::addObjectHook( QObject* object )
{ {
if ( qskCounterHook ) if ( qskCounterHook )
qskCounterHook->addObject( object ); qskCounterHook->addObject( object );
} }
static void qskRemoveObjectHook( QObject* object ) void CounterHook::removeObjectHook( QObject* object )
{ {
if ( qskCounterHook ) if ( qskCounterHook )
qskCounterHook->removeObject( object ); qskCounterHook->removeObject( object );
} }
static void qskCleanupHook() void CounterHook::cleanupHook()
{ {
if ( qskCounterHook && !qskCounterHook->isActive() ) if ( qskCounterHook && !qskCounterHook->isActive() )
{ {
@ -138,18 +201,31 @@ static void qskCleanupHook()
} }
// From now on we remove the hooks as soon as there are no counters // From now on we remove the hooks as soon as there are no counters
QskObjectCounterHook::autoDelete = true; qskAutoDeleteHook = true;
} }
static void qskInstallCleanupHookHandler() static void qskInstallCleanupHookHandler()
{ {
qAddPostRoutine( qskCleanupHook ); qAddPostRoutine( CounterHook::cleanupHook );
} }
Q_COREAPP_STARTUP_FUNCTION( qskInstallCleanupHookHandler ) Q_COREAPP_STARTUP_FUNCTION( qskInstallCleanupHookHandler )
class QskObjectCounter::PrivateData
{
public:
PrivateData( bool debugAtDestruction )
: debugAtDestruction( debugAtDestruction )
{
}
Counter counter[ 2 ];
const bool debugAtDestruction;
};
QskObjectCounter::QskObjectCounter( bool debugAtDestruction ) QskObjectCounter::QskObjectCounter( bool debugAtDestruction )
: m_debugAtDestruction( debugAtDestruction ) : m_data( new PrivateData( debugAtDestruction ) )
{ {
setActive( true ); setActive( true );
} }
@ -158,7 +234,7 @@ QskObjectCounter::~QskObjectCounter()
{ {
setActive( false ); setActive( false );
if ( m_debugAtDestruction ) if ( m_data->debugAtDestruction )
dump(); dump();
} }
@ -167,16 +243,16 @@ void QskObjectCounter::setActive( bool on )
if ( on ) if ( on )
{ {
if ( qskCounterHook == nullptr ) if ( qskCounterHook == nullptr )
qskCounterHook = new QskObjectCounterHook(); qskCounterHook = new CounterHook();
qskCounterHook->registerCounter( this, on ); qskCounterHook->registerCounters( m_data->counter, on );
} }
else else
{ {
qskCounterHook->registerCounter( this, on ); qskCounterHook->registerCounters( m_data->counter, on );
if ( !qskCounterHook->isActive() ) if ( !qskCounterHook->isActive() )
{ {
if ( QskObjectCounterHook::autoDelete ) if ( qskAutoDeleteHook )
{ {
delete qskCounterHook; delete qskCounterHook;
qskCounterHook = nullptr; qskCounterHook = nullptr;
@ -187,54 +263,38 @@ void QskObjectCounter::setActive( bool on )
bool QskObjectCounter::isActive() const bool QskObjectCounter::isActive() const
{ {
return qskCounterHook && qskCounterHook->isCounterRegistered( this ); return qskCounterHook && qskCounterHook->isCountersRegistered( m_data->counter );
}
void QskObjectCounter::addObject( QObject* object )
{
m_counter[ Objects ].increment();
if ( qskIsItem( object ) )
m_counter[ Items ].increment();
}
void QskObjectCounter::removeObject( QObject* object )
{
m_counter[ Objects ].decrement();
if ( qskIsItem( object ) )
m_counter[ Items ].decrement();
} }
void QskObjectCounter::reset() void QskObjectCounter::reset()
{ {
m_counter[ Objects ].reset(); m_data->counter[ Objects ].reset();
m_counter[ Items ].reset(); m_data->counter[ Items ].reset();
} }
int QskObjectCounter::created( ObjectType objectType ) const int QskObjectCounter::created( ObjectType objectType ) const
{ {
return m_counter[ objectType ].created; return m_data->counter[ objectType ].created;
} }
int QskObjectCounter::destroyed( ObjectType objectType ) const int QskObjectCounter::destroyed( ObjectType objectType ) const
{ {
return m_counter[ objectType ].destroyed; return m_data->counter[ objectType ].destroyed;
} }
int QskObjectCounter::current( ObjectType objectType ) const int QskObjectCounter::current( ObjectType objectType ) const
{ {
return m_counter[ objectType ].current; return m_data->counter[ objectType ].current;
} }
int QskObjectCounter::maximum( ObjectType objectType ) const int QskObjectCounter::maximum( ObjectType objectType ) const
{ {
return m_counter[ objectType ].maximum; return m_data->counter[ objectType ].maximum;
} }
void QskObjectCounter::debugStatistics( QDebug debug, ObjectType objectType ) const void QskObjectCounter::debugStatistics( QDebug debug, ObjectType objectType ) const
{ {
const Counter& c = m_counter[ objectType ]; const auto& c = m_data->counter[ objectType ];
QDebugStateSaver saver( debug ); QDebugStateSaver saver( debug );
debug.nospace(); debug.nospace();

View File

@ -7,10 +7,9 @@
#define QSK_OBJECT_COUNTER_H #define QSK_OBJECT_COUNTER_H
#include "QskGlobal.h" #include "QskGlobal.h"
#include <memory>
class QObject; class QObject;
class QDebug;
class QskObjectCounterHook;
class QSK_EXPORT QskObjectCounter class QSK_EXPORT QskObjectCounter
{ {
@ -38,51 +37,16 @@ class QSK_EXPORT QskObjectCounter
void dump() const; void dump() const;
private: private:
friend class QskObjectCounterHook; class PrivateData;
std::unique_ptr< PrivateData > m_data;
void addObject( QObject* );
void removeObject( QObject* );
class Counter
{
public:
Counter()
{
reset();
}
void reset()
{
created = destroyed = current = maximum = 0;
}
void increment()
{
created++;
current++;
if ( current > maximum )
maximum = current;
}
void decrement()
{
destroyed++;
current--;
}
int created;
int destroyed;
int current;
int maximum;
};
Counter m_counter[ 2 ];
const bool m_debugAtDestruction;
}; };
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
class QDebug;
QSK_EXPORT QDebug operator<<( QDebug, const QskObjectCounter& ); QSK_EXPORT QDebug operator<<( QDebug, const QskObjectCounter& );
#endif #endif
#endif #endif