code improved

This commit is contained in:
Uwe Rathmann 2018-02-07 15:40:05 +01:00
parent 8553ecc354
commit 38ed90b659
1 changed files with 84 additions and 40 deletions

View File

@ -14,14 +14,6 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qobject_p.h> #include <private/qobject_p.h>
QSK_QT_PRIVATE_END QSK_QT_PRIVATE_END
static struct
{
QHooks::StartupCallback startup;
QHooks::AddQObjectCallback addObject;
QHooks::RemoveQObjectCallback removeObject;
} qskOtherHooks;
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 ) );
@ -29,16 +21,38 @@ static inline bool qskIsItem( const QObject* object )
/* /*
The addObject hook is called from the constructor of QObject, The addObject hook is called from the constructor of QObject,
where we don't have the derived class constructed yet. where we don't have the derived class constructed yet.
So we can't cast the object itself and also have to rely on So we can't cast the object itself and also have to rely on
RTTI being enabled. TODO ... RTTI being enabled. TODO ...
*/ */
return dynamic_cast< QQuickItemPrivate* >( o_p ) != nullptr; return dynamic_cast< QQuickItemPrivate* >( o_p ) != nullptr;
} }
static void qskStartupHook();
static void qskAddObjectHook( QObject* );
static void qskRemoveObjectHook( QObject* );
class QskObjectCounterHook class QskObjectCounterHook
{ {
public: public:
QskObjectCounterHook()
{
m_otherStartup = qtHookData[QHooks::Startup];
m_otherAddObject = qtHookData[QHooks::AddQObject];
m_otherRemoveObject = qtHookData[QHooks::RemoveQObject];
qtHookData[QHooks::Startup] = reinterpret_cast< quintptr >( &qskStartupHook );
qtHookData[QHooks::AddQObject] = reinterpret_cast< quintptr >( &qskAddObjectHook );
qtHookData[QHooks::RemoveQObject] = reinterpret_cast< quintptr >( &qskRemoveObjectHook );
}
~QskObjectCounterHook()
{
qtHookData[QHooks::Startup] = m_otherStartup;
qtHookData[QHooks::AddQObject] = m_otherAddObject;
qtHookData[QHooks::RemoveQObject] = m_otherRemoveObject;
}
void registerCounter( QskObjectCounter* counter, bool on ) void registerCounter( QskObjectCounter* counter, bool on )
{ {
if ( on ) if ( on )
@ -52,76 +66,88 @@ public:
return m_counterSet.contains( const_cast< QskObjectCounter* >( counter ) ); return m_counterSet.contains( const_cast< QskObjectCounter* >( counter ) );
} }
void startup() const bool isActive() const
{
return !m_counterSet.isEmpty();
}
void startup()
{ {
#if 0 #if 0
qDebug() << "** QskObjectCounterHook enabled"; qDebug() << "** QskObjectCounterHook enabled";
#endif #endif
if ( m_otherStartup )
reinterpret_cast< QHooks::StartupCallback >( m_otherStartup )();
} }
void addObject( QObject* object ) void addObject( QObject* object )
{ {
for ( auto counter : qskAsConst( m_counterSet ) ) for ( auto counter : qskAsConst( m_counterSet ) )
counter->addObject( object ); counter->addObject( object );
if ( m_otherAddObject )
reinterpret_cast< QHooks::AddQObjectCallback >( m_otherAddObject )( object );
} }
void removeObject( QObject* object ) void removeObject( QObject* object )
{ {
for ( auto counter : qskAsConst( m_counterSet ) ) for ( auto counter : qskAsConst( m_counterSet ) )
counter->removeObject( object ); counter->removeObject( object );
if ( m_otherRemoveObject )
reinterpret_cast< QHooks::RemoveQObjectCallback >( m_otherRemoveObject )( object );
} }
static bool autoDelete;
private: private:
QSet< QskObjectCounter* > m_counterSet; QSet< QskObjectCounter* > m_counterSet;
quintptr m_otherStartup;
quintptr m_otherAddObject;
quintptr m_otherRemoveObject;
}; };
static QskObjectCounterHook* qskCounterHook(); bool QskObjectCounterHook::autoDelete = false;
static QskObjectCounterHook* qskCounterHook = nullptr;
static void qskStartupHook() static void qskStartupHook()
{ {
qskCounterHook()->startup(); if ( qskCounterHook )
qskCounterHook->startup();
if ( qskOtherHooks.startup )
qskOtherHooks.startup();
} }
static void qskAddObjectHook( QObject* object ) static void qskAddObjectHook( QObject* object )
{ {
qskCounterHook()->addObject( object ); if ( qskCounterHook )
qskCounterHook->addObject( object );
if ( qskOtherHooks.addObject )
qskOtherHooks.addObject( object );
} }
static void qskRemoveObjectHook( QObject* object ) static void qskRemoveObjectHook( QObject* object )
{ {
qskCounterHook()->removeObject( object ); if ( qskCounterHook )
qskCounterHook->removeObject( object );
if ( qskOtherHooks.removeObject )
qskOtherHooks.removeObject( object );
} }
static QskObjectCounterHook* qskCounterHook() static void qskCleanupHook()
{ {
static bool isInitialized = false; if ( qskCounterHook && !qskCounterHook->isActive() )
if ( !isInitialized )
{ {
qskOtherHooks.startup = reinterpret_cast< QHooks::StartupCallback >( qtHookData[QHooks::Startup] ); delete qskCounterHook;
qskOtherHooks.addObject = reinterpret_cast< QHooks::AddQObjectCallback >( qtHookData[QHooks::AddQObject] ); qskCounterHook = nullptr;
qskOtherHooks.removeObject = reinterpret_cast< QHooks::RemoveQObjectCallback >( qtHookData[QHooks::RemoveQObject] );
qtHookData[QHooks::Startup] = reinterpret_cast< quintptr >( &qskStartupHook );
qtHookData[QHooks::AddQObject] = reinterpret_cast< quintptr >( &qskAddObjectHook );
qtHookData[QHooks::RemoveQObject] = reinterpret_cast< quintptr >( &qskRemoveObjectHook );
isInitialized = true;
} }
static QskObjectCounterHook counterHook; // From now on we remove the hooks as soon as there are no counters
return &counterHook; QskObjectCounterHook::autoDelete = true;
} }
static void qskInstallCleanupHookHandler()
{
qAddPostRoutine( qskCleanupHook );
}
Q_COREAPP_STARTUP_FUNCTION( qskInstallCleanupHookHandler )
QskObjectCounter::QskObjectCounter( bool debugAtDestruction ): QskObjectCounter::QskObjectCounter( bool debugAtDestruction ):
m_debugAtDestruction( debugAtDestruction ) m_debugAtDestruction( debugAtDestruction )
{ {
@ -138,12 +164,30 @@ QskObjectCounter::~QskObjectCounter()
void QskObjectCounter::setActive( bool on ) void QskObjectCounter::setActive( bool on )
{ {
qskCounterHook()->registerCounter( this, on ); if ( on )
{
if ( qskCounterHook == nullptr )
qskCounterHook = new QskObjectCounterHook();
qskCounterHook->registerCounter( this, on );
}
else
{
qskCounterHook->registerCounter( this, on );
if ( !qskCounterHook->isActive() )
{
if ( QskObjectCounterHook::autoDelete )
{
delete qskCounterHook;
qskCounterHook = nullptr;
}
}
}
} }
bool QskObjectCounter::isActive() const bool QskObjectCounter::isActive() const
{ {
return qskCounterHook()->isCounterRegistered( this ); return qskCounterHook && qskCounterHook->isCounterRegistered( this );
} }
void QskObjectCounter::addObject( QObject* object ) void QskObjectCounter::addObject( QObject* object )