diff --git a/src/common/QskMetaCallback.cpp b/src/common/QskMetaCallback.cpp index 83a6dbb9..27aecd3a 100644 --- a/src/common/QskMetaCallback.cpp +++ b/src/common/QskMetaCallback.cpp @@ -33,7 +33,7 @@ static inline void qskInvokeMethodQueued( QObject* object, QskMetaCallback::QskMetaCallback( const QObject* object, const QMetaMethod& method, Qt::ConnectionType connectionType ): m_object( const_cast< QObject* >( object ) ), - m_methodData { method.enclosingMetaObject(), method.methodIndex() }, + m_methodData { method.enclosingMetaObject(), method.methodIndex() }, m_type( MetaMethod ), m_hasObject( object != nullptr ), m_connectionType( static_cast< ushort >( connectionType & 0x3 ) ) @@ -101,7 +101,7 @@ QskMetaCallback& QskMetaCallback::operator=( const QskMetaCallback& other ) { if ( m_type == MetaFunction && m_functionData.invokable ) m_functionData.invokable->destroyIfLastRef(); - + m_methodData.metaObject = other.m_methodData.metaObject; m_methodData.methodIndex = other.m_methodData.methodIndex; @@ -341,7 +341,7 @@ void qskInvokeMethod( QObject* object, if ( connectionType == Qt::QueuedConnection ) { - qskInvokeMethodQueued( object, + qskInvokeMethodQueued( object, metaObject, methodIndex, paramCount + 1, types, args ); } else diff --git a/src/common/QskMetaCallback.h b/src/common/QskMetaCallback.h index 0a5f7a62..ebf3ba48 100644 --- a/src/common/QskMetaCallback.h +++ b/src/common/QskMetaCallback.h @@ -100,12 +100,12 @@ inline Qt::ConnectionType QskMetaCallback::connectionType() const } QSK_EXPORT void qskInvokeMethod( - QObject* object, const QMetaMethod&, void* args[], - Qt::ConnectionType = Qt::AutoConnection ); + QObject* object, const QMetaMethod&, void* args[], + Qt::ConnectionType = Qt::AutoConnection ); QSK_EXPORT void qskInvokeMethod( - QObject* object, const QMetaObject*, int methodIndex, void* args[], - Qt::ConnectionType = Qt::AutoConnection ); + QObject* object, const QMetaObject*, int methodIndex, void* args[], + Qt::ConnectionType = Qt::AutoConnection ); Q_DECLARE_METATYPE( QskMetaCallback ) diff --git a/src/common/QskMetaFunction.cpp b/src/common/QskMetaFunction.cpp index 9f2d21ea..4077f237 100644 --- a/src/common/QskMetaFunction.cpp +++ b/src/common/QskMetaFunction.cpp @@ -109,7 +109,7 @@ size_t QskMetaFunction::parameterCount() const { if ( m_parameterTypes ) { - for ( int i = 1; ; i++ ) + for ( int i = 1;; i++ ) { if ( m_parameterTypes[ i ] == QMetaType::UnknownType ) return i + 1; // including the return type diff --git a/src/common/QskMetaFunction.h b/src/common/QskMetaFunction.h index 1e18c78b..4052ddb0 100644 --- a/src/common/QskMetaFunction.h +++ b/src/common/QskMetaFunction.h @@ -87,29 +87,6 @@ protected: QskMetaInvokable* invokable() const; private: - template< typename T, typename F > - static inline QskMetaInvokable* findInvokable( F function ) - { - QskMetaInvokable* invokable; - -#if QSK_SHARED_META_INVOKABLE - invokable = QskMetaInvokable::find( typeid( T ) ); - if ( invokable ) - { - invokable->ref(); - } - else - { - invokable = new T( function ); - QskMetaInvokable::insert( typeid( T ), invokable ); - } -#else - invokable = new T( function ); -#endif - - return invokable; - } - QskMetaInvokable* m_invokable; const int* m_parameterTypes; }; @@ -133,10 +110,12 @@ inline QskMetaFunction::QskMetaFunction( T function ) const int Argc = Traits::ArgumentCount; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; - using Invokable = QskMetaMemberInvokable< T, Args, void >; - - init( findInvokable( function ), - ConnectionTypes< typename Traits::Arguments >::types() ); + + auto invokable = QskMetaInvokable::instance( + QskMetaMemberInvokable< T, Args, void >::invoke, + reinterpret_cast< void** >( &function ) ); + + init( invokable, ConnectionTypes< typename Traits::Arguments >::types() ); } template< typename T, QskMetaFunctionTraits::IsFunction< T >* > @@ -148,10 +127,12 @@ inline QskMetaFunction::QskMetaFunction( T function ) const int Argc = Traits::ArgumentCount; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; - using Invokable = QskMetaFunctionInvokable< T, Args, void >; - init( findInvokable( function ), - ConnectionTypes< typename Traits::Arguments >::types() ); + auto invokable = QskMetaInvokable::instance( + QskMetaFunctionInvokable< T, Args, void >::invoke, + reinterpret_cast< void** >( &function ) ); + + init( invokable, ConnectionTypes< typename Traits::Arguments >::types() ); } template< typename T, QskMetaFunctionTraits::IsFunctor< T >* > @@ -163,10 +144,12 @@ inline QskMetaFunction::QskMetaFunction( T functor ) const int Argc = Traits::ArgumentCount; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; - using Invokable = QskMetaFunctorInvokable< T, Argc, Args, void >; - init( findInvokable( functor ), - ConnectionTypes< typename Traits::Arguments >::types() ); + auto invokable = QskMetaInvokable::instance( + QskMetaFunctorInvokable< T, Argc, Args, void >::invoke, + reinterpret_cast< void** >( &functor ) ); + + init( invokable, ConnectionTypes< typename Traits::Arguments >::types() ); } Q_DECLARE_METATYPE( QskMetaFunction ) diff --git a/src/common/QskMetaInvokable.cpp b/src/common/QskMetaInvokable.cpp index 2f15ff9a..6940200d 100644 --- a/src/common/QskMetaInvokable.cpp +++ b/src/common/QskMetaInvokable.cpp @@ -18,6 +18,27 @@ namespace "Bad cast: QskMetaInvokable does not match" ); } +QskMetaInvokable* QskMetaInvokable::instance( + InvokeFunction invoke, void** functor ) +{ + /* + In opposite to QObject::connect we share the Invokable for callbacks to the same + function/functor - like f.e QQuickItem::update(). But we have to pay an extra static + pointer inside of each callback instance. + */ + QskMetaInvokable* invokable; + void* args[] = { &invokable, functor }; + + invoke( Find, nullptr, nullptr, args, nullptr ); + + if ( invokable ) + invokable->ref(); + else + invoke( Create, nullptr, nullptr, args, nullptr ); + + return invokable; +} + int QskMetaInvokable::typeInfo() const { auto that = const_cast< QskMetaInvokable* >( this ); @@ -35,28 +56,3 @@ int QskMetaInvokable::refCount() const auto that = const_cast< QskMetaInvokable* >( this ); return reinterpret_cast< SlotObject* >( that )->ref.load(); } - -#if QSK_SHARED_META_INVOKABLE - -#include -#include - -static std::unordered_map< std::type_index, QskMetaInvokable* > qskInvokableTab; - -QskMetaInvokable* QskMetaInvokable::find( const std::type_info& info ) -{ - const auto it = qskInvokableTab.find( info ); - return ( it != qskInvokableTab.end() ) ? it->second : nullptr; -} - -void QskMetaInvokable::insert( const std::type_info& info, QskMetaInvokable* invokable ) -{ - qskInvokableTab.emplace( info, invokable ); -} - -void QskMetaInvokable::remove( const std::type_info& info ) -{ - qskInvokableTab.erase( info ); -} - -#endif // QSK_SHARED_META_INVOKABLE diff --git a/src/common/QskMetaInvokable.h b/src/common/QskMetaInvokable.h index ad0a32b3..f6b7543d 100644 --- a/src/common/QskMetaInvokable.h +++ b/src/common/QskMetaInvokable.h @@ -11,132 +11,133 @@ // helper classes for QskMetaFunction -#ifndef QT_NO_RTTI // we rely on hashing type_info - - /* - When being enabled the same instance of QskMetaInvokable is used - for all QskMetaFunctions having the same function/method/functor - - f.e. &QQuickItem::update. - - Not sure, why QObject::connect does not do the same and always - creates unique QSlotObjectBase objects for each connection. - */ - #ifndef QSK_SHARED_META_INVOKABLE - #define QSK_SHARED_META_INVOKABLE 1 - #endif -#endif - class QSK_EXPORT QskMetaInvokable : public QtPrivate::QSlotObjectBase { public: typedef void (* InvokeFunction)( int which, QtPrivate::QSlotObjectBase*, QObject*, void**, bool* ); - enum { TypeInfo = NumOperations + 1 }; + enum + { + TypeInfo = NumOperations + 1, + Create, + Find + }; int typeInfo() const; int refCount() const; -protected: - friend class QskMetaFunction; + static QskMetaInvokable* instance( InvokeFunction, void** function ); +protected: explicit QskMetaInvokable( InvokeFunction f ): QSlotObjectBase( f ) { } - -#if QSK_SHARED_META_INVOKABLE - /* - To avoid having more QskMetaInvokables for the same - function we have a hash table, where they are registered - */ - static QskMetaInvokable* find( const std::type_info& info ); - static void insert( const std::type_info&, QskMetaInvokable* ); - static void remove( const std::type_info& ); -#else - -#endif }; template< typename Function, typename Args, typename R > class QskMetaFunctionInvokable : public QskMetaInvokable { -public: - typedef QtPrivate::FunctionPointer< Function > FuncType; + using Invokable = QskMetaFunctionInvokable< Function, Args, R >; - explicit QskMetaFunctionInvokable( Function function ): +public: + explicit inline QskMetaFunctionInvokable( Function function ): QskMetaInvokable( &invoke ), m_function( function ) { } - static void invoke(int which, QtPrivate::QSlotObjectBase* invokable, + static void invoke(int which, QtPrivate::QSlotObjectBase*, QObject* object, void** args, bool* ) { - auto invokableFunction = static_cast< QskMetaFunctionInvokable* >( invokable ); + static Invokable* invokable = nullptr; switch ( which ) { + case Find: + { + *reinterpret_cast< void** >( args[0] ) = invokable; + break; + } + case Create: + { + invokable = new Invokable( *reinterpret_cast< Function* >( args[1] ) ); + *reinterpret_cast< void** >( args[0] ) = invokable; + + break; + } case Destroy: { -#if QSK_SHARE_INVOKABLES - remove( typeid( Function ) ); -#endif - delete invokableFunction; + delete invokable; + invokable = nullptr; break; } case Call: { + typedef QtPrivate::FunctionPointer< Function > FuncType; + FuncType::template call< Args, R >( - invokableFunction->m_function, object, args ); + invokable->m_function, object, args ); break; } case TypeInfo: { - int* typeInfo = reinterpret_cast< int* >( args ); - *typeInfo = 1; // = QskMetaFunction::Function - + *reinterpret_cast< int* >( args ) = 1; // QskMetaFunction::Function break; } } } +private: Function m_function; }; template< typename Function, typename Args, typename R > class QskMetaMemberInvokable : public QskMetaInvokable { + using Invokable = QskMetaMemberInvokable< Function, Args, R >; + public: - explicit QskMetaMemberInvokable( Function function ): + explicit inline QskMetaMemberInvokable( Function function ): QskMetaInvokable( &invoke ), m_function( function ) { } - static void invoke( int which, QtPrivate::QSlotObjectBase* invokable, + static void invoke( int which, QtPrivate::QSlotObjectBase*, QObject* object, void** args, bool* ret ) { - typedef QtPrivate::FunctionPointer< Function > FuncType; - - auto invokableMember = static_cast< QskMetaMemberInvokable* >( invokable ); + static Invokable* invokable = nullptr; switch (which) { + case Find: + { + *reinterpret_cast< void** >( args[0] ) = invokable; + break; + } + case Create: + { + invokable = new Invokable( *reinterpret_cast< Function* >( args[1] ) ); + *reinterpret_cast< void** >( args[0] ) = invokable; + + break; + } case Destroy: { -#if QSK_SHARE_INVOKABLES - remove( typeid( Function ) ); -#endif - delete invokableMember; + delete invokable; + invokable = nullptr; break; } case Call: { + typedef QtPrivate::FunctionPointer< Function > FuncType; + FuncType::template call< Args, R >( - invokableMember->m_function, + invokable->m_function, static_cast< typename FuncType::Object* >( object ), args ); break; @@ -144,14 +145,12 @@ public: case Compare: { const auto function = *reinterpret_cast< Function* >( args ); - *ret = function == invokableMember->m_function; + *ret = function == invokable->m_function; break; } case TypeInfo: { - int* typeInfo = reinterpret_cast< int* >( args ); - *typeInfo = 0; // = QskMetaFunction::Member - + *reinterpret_cast< int* >( args ) = 0; // = QskMetaFunction::Member break; } } @@ -164,42 +163,52 @@ private: template< typename Function, int N, typename Args, typename R > class QskMetaFunctorInvokable : public QskMetaInvokable { -public: - typedef QtPrivate::Functor< Function, N > FuncType; + using Invokable = QskMetaFunctorInvokable< Function, N, Args, R >; - explicit QskMetaFunctorInvokable( Function function ): +public: + explicit inline QskMetaFunctorInvokable( Function function ): QskMetaInvokable( &invoke ), - m_function( std::move( function ) ) + m_function( function ) { } - static void invoke( int which, QSlotObjectBase* invokable, - QObject* object, void** args, bool* ) + static void invoke( int which, QSlotObjectBase*, QObject* object, void** args, bool* ) { - auto invokableFunctor = static_cast< QskMetaFunctorInvokable* >( invokable ); + static Invokable* invokable = nullptr; switch (which) { + case Find: + { + *reinterpret_cast< void** >( args[0] ) = invokable; + break; + } + case Create: + { + invokable = new Invokable( *reinterpret_cast< Function* >( args[1] ) ); + *reinterpret_cast< void** >( args[0] ) = invokable; + + break; + } case Destroy: { -#if QSK_SHARE_INVOKABLES - remove( typeid( Function ) ); -#endif - delete invokableFunctor; + delete invokable; + invokable = nullptr; break; } case Call: { + typedef QtPrivate::Functor< Function, N > FuncType; + FuncType::template call< Args, R >( - invokableFunctor->m_function, object, args ); + invokable->m_function, object, args ); + break; } case TypeInfo: { - int* typeInfo = reinterpret_cast< int* >( args ); - *typeInfo = 2; // QskMetaFunction::Functor; - + *reinterpret_cast< int* >( args ) = 2; // QskMetaFunction::Functor break; } }