diff --git a/src/common/QskMetaCall.cpp b/src/common/QskMetaCall.cpp deleted file mode 100644 index e6cda416..00000000 --- a/src/common/QskMetaCall.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#include "QskMetaCall.h" -#include -#include -#include -#include -#include - -#include - -namespace -{ - // to get access to the private section of QSlotObjectBase - struct SlotObject - { - QAtomicInt ref; - QskMetaCall::Invokable::InvokeFunction invoke; - }; -} - -namespace QskMetaCall -{ - inline Invokable::InvokeFunction invokeCall( const Invokable* invokable ) - { - return ( ( SlotObject* )( invokable ) )->invoke; - } - - int Invokable::typeInfo() const - { - int value; - - auto f = invokeCall( this ); - - f( TypeInfo, const_cast< Invokable* >( this ), - nullptr, reinterpret_cast< void** >( &value ), nullptr ); - - return value; - } - - int Invokable::refCount() const - { - return ( ( SlotObject* )( this ) )->ref.load(); - } -} - -namespace -{ - using namespace QskMetaCall; - - class FunctionCallEvent : public QMetaCallEvent - { - public: - FunctionCallEvent( Invokable* invokable, - int nargs, int* types, void* args[], QSemaphore* semaphore = nullptr ): - QMetaCallEvent( invokable, nullptr, 0, nargs, types, args, semaphore ), - m_invokable ( invokable ) - { - } - - virtual ~FunctionCallEvent() - { - } - - private: - Invokable* m_invokable; - }; - - class MethodCallEvent : public QMetaCallEvent - { - public: - MethodCallEvent( const QMetaObject* mo, ushort methodIndex, - int nargs, int* types, void* args[], QSemaphore* semaphore = nullptr ): - QMetaCallEvent( - mo->methodOffset(), methodIndex, mo->d.static_metacall, - nullptr, -1, nargs, types, args, semaphore ) - { - } - - virtual ~MethodCallEvent() - { - } - }; -} - -void QskMetaCall::invoke( QObject* object, - const QMetaMethod& method, void* args[], - Qt::ConnectionType connectionType ) -{ - auto metaObject = method.enclosingMetaObject(); - - const int methodOffset = metaObject->methodOffset(); - const int methodIndex = method.methodIndex() - methodOffset; - - if ( connectionType == Qt::AutoConnection ) - { - connectionType = ( object->thread() == QThread::currentThread() ) - ? Qt::DirectConnection : Qt::QueuedConnection; - } - - if ( connectionType == Qt::DirectConnection ) - { - if ( metaObject->d.static_metacall ) - { - metaObject->d.static_metacall(object, - QMetaObject::InvokeMetaMethod, methodIndex, args ); - } - else - { - QMetaObject::metacall( object, - QMetaObject::InvokeMetaMethod, methodIndex, args ); - } - } - else - { - const int paramCount = method.parameterCount(); - - auto types = static_cast< int* >( malloc( paramCount * sizeof( int ) ) ); - auto arguments = static_cast< void** >( malloc( paramCount * sizeof( void* ) ) ); - - types[0] = QMetaType::UnknownType; // a return type is not possible - arguments[0] = nullptr; - - for ( int i = 1; i < paramCount; i++ ) - { - if ( arguments[i] == nullptr ) - { - Q_ASSERT( arguments[i] != nullptr ); - - free( types ); - free( arguments ); - - return; - } - - types[i] = method.parameterType( i ); - arguments[i] = args[i - 1]; - } - - Q_ASSERT( args[paramCount] == nullptr ); - - if ( connectionType == Qt::QueuedConnection ) - { - auto event = new MethodCallEvent( - metaObject, methodIndex, paramCount + 1, types, args ); - - QCoreApplication::postEvent(object, event ); - } - else - { - QSemaphore semaphore; - - auto event = new MethodCallEvent( - metaObject, methodIndex, paramCount + 1, types, args, &semaphore ); - - QCoreApplication::postEvent( object, event ); - - semaphore.acquire(); - } - } -} - -void QskMetaCall::invoke( QObject* object, - const Invokable& invokable, int argc, const int argTypes[], void* argv[], - Qt::ConnectionType connectionType ) -{ - //connectionType &= ~Qt::UniqueConnection; - - auto invokablePtr = const_cast< Invokable* >( &invokable ); - - if ( connectionType == Qt::AutoConnection ) - { - connectionType = ( object->thread() == QThread::currentThread() ) - ? Qt::DirectConnection : Qt::QueuedConnection; - } - - if ( connectionType == Qt::DirectConnection ) - { - invokablePtr->call( object, argv ); - } - else - { - auto types = static_cast< int* >( malloc( argc * sizeof( int ) ) ); - auto arguments = static_cast< void** >( malloc( argc * sizeof( void* ) ) ); - - types[0] = QMetaType::UnknownType; // a return type is not possible - arguments[0] = nullptr; - - for ( int i = 1; i < argc; i++ ) - { - if ( argv[i] == nullptr ) - { - Q_ASSERT( arguments[i] != nullptr ); - - free( types ); - free( arguments ); - - return; - } - - types[i] = argTypes[i - 1]; - arguments[i] = QMetaType::create( argTypes[i - 1], argv[i] ); - } - - if ( connectionType == Qt::QueuedConnection ) - { - auto event = new FunctionCallEvent( - invokablePtr, argc, types, arguments, nullptr ); - - QCoreApplication::postEvent( object, event ); - } - else // Qt::BlockingQueuedConnection ??? - { - // .... - } - } -} diff --git a/src/common/QskMetaCall.h b/src/common/QskMetaCall.h deleted file mode 100644 index c9c20b28..00000000 --- a/src/common/QskMetaCall.h +++ /dev/null @@ -1,198 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#ifndef QSK_META_CALL_H -#define QSK_META_CALL_H 1 - -#include "QskGlobal.h" -#include - -namespace QskMetaCall -{ - class Invokable; - - QSK_EXPORT void invoke( QObject* object, - const QMetaMethod&, void* args[], - Qt::ConnectionType = Qt::AutoConnection ); - - QSK_EXPORT void invoke( QObject*, - const Invokable&, int argc, const int argTypes[], void* args[], - Qt::ConnectionType = Qt::AutoConnection ); -} - -namespace QskMetaCall -{ - using namespace QtPrivate; - - class QSK_EXPORT Invokable : public QSlotObjectBase - { - public: - typedef void (* InvokeFunction)( int which, QSlotObjectBase*, - QObject*, void**, bool* ); - - enum { TypeInfo = NumOperations + 1 }; - - int typeInfo() const; - int refCount() const; - - protected: - explicit Invokable( InvokeFunction f ): - QSlotObjectBase( f ) - { - } - }; - - template< typename Func, typename Args, typename R > - class FunctionInvokable : public Invokable - { - public: - typedef FunctionPointer< Func > FuncType; - - explicit FunctionInvokable( Func f ): - Invokable( &invoke ), - function(f) - { - } - - static void invoke(int which, QSlotObjectBase* invokable, - QObject* object, void** args, bool* ) - { - auto f = static_cast< FunctionInvokable* >( invokable ); - - switch ( which ) - { - case Destroy: - { - delete f; - break; - } - case Call: - { - FuncType::template call< Args, R >( f->function, object, args ); - break; - } - case TypeInfo: - { - int* typeInfo = reinterpret_cast< int* >( args ); - //*typeInfo = QskMetaFunction::Function; - *typeInfo = 1; - - break; - } - } - } - - Func function; - }; - - template< typename Func, typename Args, typename R > - class MemberFunctionInvokable : public Invokable - { - public: - explicit MemberFunctionInvokable( Func f ): - Invokable( &invoke ), - function(f) - { - } - - static void invoke( int which, QSlotObjectBase* invokable, - QObject* object, void** args, bool* ret ) - { - typedef FunctionPointer< Func > FuncType; - - auto f = static_cast< MemberFunctionInvokable* >( invokable ); - - switch (which) - { - case Destroy: - { - delete f; - break; - } - case Call: - { - FuncType::template call< Args, R >( - f->function, static_cast< typename FuncType::Object* >( object ), args ); - - break; - } - case Compare: - { - *ret = *reinterpret_cast< Func* >( args ) == f->function; - break; - } - case TypeInfo: - { - int* typeInfo = reinterpret_cast< int* >( args ); - *typeInfo = 0; - //*typeInfo = QskMetaFunction::Member; - - break; - } - } - } - - private: - Func function; - }; - - template< typename Func, int N, typename Args, typename R > - class FunctorInvokable : public Invokable - { - public: - typedef Functor< Func, N > FuncType; - - explicit FunctorInvokable( Func f ): - Invokable( &invoke ), - function( std::move( f ) ) - { - } - - static void invoke( int which, QSlotObjectBase* invokable, - QObject* object, void** args, bool* ) - { - auto f = static_cast< FunctorInvokable* >( invokable ); - - switch (which) - { - case Destroy: - { - delete f; - break; - } - case Call: - { - FuncType::template call< Args, R >( f->function, object, args ); - break; - } - case TypeInfo: - { - int* typeInfo = reinterpret_cast< int* >( args ); - *typeInfo = 2; - //*typeInfo = QskMetaFunction::Functor; - - break; - } - } - } - - private: - Func function; - }; - - template< typename T > - using IsMemberFunction = typename std::enable_if< FunctionPointer< T >::IsPointerToMemberFunction, - std::true_type >::type; - - template< typename T > - using IsFunction = typename std::enable_if< !FunctionPointer< T >::IsPointerToMemberFunction - && FunctionPointer< T >::ArgumentCount >= 0, std::true_type >::type; - - template< typename T > - using IsFunctor = typename std::enable_if< !FunctionPointer< T >::IsPointerToMemberFunction - && FunctionPointer< T >::ArgumentCount == -1, std::true_type >::type; -} - -#endif diff --git a/src/common/QskMetaCallback.cpp b/src/common/QskMetaCallback.cpp index a35d2521..684b45f9 100644 --- a/src/common/QskMetaCallback.cpp +++ b/src/common/QskMetaCallback.cpp @@ -4,8 +4,29 @@ *****************************************************************************/ #include "QskMetaCallback.h" + #include -#include +#include +#include +#include + +QSK_QT_PRIVATE_BEGIN +#include +QSK_QT_PRIVATE_END + +static inline void qskInvokeMethodQueued( QObject* object, + const QMetaObject* metaObject, ushort methodIndex, + int nargs, int* types, void* args[], QSemaphore* semaphore = nullptr ) +{ + constexpr QObject* sender = nullptr; + constexpr int signalId = -1; + + auto event = new QMetaCallEvent( + metaObject->methodOffset(), methodIndex, metaObject->d.static_metacall, + sender, signalId, nargs, types, args, semaphore ); + + QCoreApplication::postEvent( object, event ); +} QskMetaCallback::QskMetaCallback( const QObject* object, const QMetaMethod& method, Qt::ConnectionType connectionType ): @@ -147,8 +168,7 @@ void QskMetaCallback::invoke( void* args[] ) { case MetaMethod: { - if ( object ) - QskMetaCall::invoke( object, *m_method, args, connectionType() ); + qskInvokeMethod( object, *m_method, args, connectionType() ); break; } case MetaFunction: @@ -161,3 +181,80 @@ void QskMetaCallback::invoke( void* args[] ) break; } } + + +void qskInvokeMethod( QObject* object, + const QMetaMethod& method, void* args[], + Qt::ConnectionType connectionType ) +{ + if ( object == nullptr ) + return; + + auto metaObject = method.enclosingMetaObject(); + + const int methodOffset = metaObject->methodOffset(); + const int methodIndex = method.methodIndex() - methodOffset; + + if ( connectionType == Qt::AutoConnection ) + { + connectionType = ( object->thread() == QThread::currentThread() ) + ? Qt::DirectConnection : Qt::QueuedConnection; + } + + if ( connectionType == Qt::DirectConnection ) + { + if ( metaObject->d.static_metacall ) + { + metaObject->d.static_metacall(object, + QMetaObject::InvokeMetaMethod, methodIndex, args ); + } + else + { + QMetaObject::metacall( object, + QMetaObject::InvokeMetaMethod, methodIndex, args ); + } + } + else + { + const int paramCount = method.parameterCount(); + + auto types = static_cast< int* >( malloc( paramCount * sizeof( int ) ) ); + auto arguments = static_cast< void** >( malloc( paramCount * sizeof( void* ) ) ); + + types[0] = QMetaType::UnknownType; // a return type is not possible + arguments[0] = nullptr; + + for ( int i = 1; i < paramCount; i++ ) + { + if ( arguments[i] == nullptr ) + { + Q_ASSERT( arguments[i] != nullptr ); + + free( types ); + free( arguments ); + + return; + } + + types[i] = method.parameterType( i ); + arguments[i] = args[i - 1]; + } + + Q_ASSERT( args[paramCount] == nullptr ); + + if ( connectionType == Qt::QueuedConnection ) + { + qskInvokeMethodQueued( object, + metaObject, methodIndex, paramCount + 1, types, args ); + } + else + { + QSemaphore semaphore; + + qskInvokeMethodQueued( object, + metaObject, methodIndex, paramCount + 1, types, args, &semaphore ); + + semaphore.acquire(); + } + } +} diff --git a/src/common/QskMetaCallback.h b/src/common/QskMetaCallback.h index 2207b3c6..812424c9 100644 --- a/src/common/QskMetaCallback.h +++ b/src/common/QskMetaCallback.h @@ -89,6 +89,10 @@ inline Qt::ConnectionType QskMetaCallback::connectionType() const return static_cast< Qt::ConnectionType >( m_connectionType ); } +QSK_EXPORT void qskInvokeMethod( + QObject* object, const QMetaMethod&, void* args[], + Qt::ConnectionType = Qt::AutoConnection ); + Q_DECLARE_METATYPE( QskMetaCallback ) #endif diff --git a/src/common/QskMetaFunction.cpp b/src/common/QskMetaFunction.cpp index 7cbde28c..4214c4e9 100644 --- a/src/common/QskMetaFunction.cpp +++ b/src/common/QskMetaFunction.cpp @@ -4,9 +4,30 @@ *****************************************************************************/ #include "QskGlobal.h" -#include "QskMetaCall.h" #include "QskMetaFunction.h" +#include +#include +#include +#include + +QSK_QT_PRIVATE_BEGIN +#include +QSK_QT_PRIVATE_END + +static inline void qskInvokeFunctionQueued( QObject* object, + QskMetaInvokable* invokable, int argc, int* types, void* argv[], + QSemaphore* semaphore = nullptr ) +{ + constexpr QObject* sender = nullptr; + constexpr int signalId = 0; + + auto event = new QMetaCallEvent( + invokable, sender, signalId, argc, types, argv, semaphore ); + + QCoreApplication::postEvent( object, event ); +} + QskMetaFunction::QskMetaFunction(): m_invokable( nullptr ), m_parameterTypes( nullptr ) @@ -68,15 +89,10 @@ QskMetaFunction& QskMetaFunction::operator=( const QskMetaFunction& other ) return *this; } -void QskMetaFunction::init( QskMetaCall::Invokable* invokable, +void QskMetaFunction::init( QskMetaInvokable* invokable, const int* parameterTypes ) { m_invokable = invokable; -#if 0 - if ( m_invokable ) - m_invokable->ref(); -#endif - m_parameterTypes = parameterTypes; } @@ -111,9 +127,78 @@ QskMetaFunction::Type QskMetaFunction::functionType() const void QskMetaFunction::invoke( QObject* object, void* argv[], Qt::ConnectionType connectionType ) { - if ( m_invokable ) + if ( m_invokable == nullptr ) + return; + + int invokeType = connectionType & 0x3; + + if ( invokeType == Qt::AutoConnection ) { - QskMetaCall::invoke( object, *m_invokable, - parameterCount(), parameterTypes(), argv, connectionType ); + invokeType = ( object->thread() == QThread::currentThread() ) + ? Qt::DirectConnection : Qt::QueuedConnection; + } + else if ( invokeType == Qt::BlockingQueuedConnection ) + { + if ( object->thread() == QThread::currentThread() ) + { + // We would end up in a deadlock, better do nothing + return; + } + } + + if ( invokeType == Qt::DirectConnection ) + { + m_invokable->call( object, argv ); + } + else + { + if ( object == nullptr ) + { +#if 1 + /* + object might be deleted in another thread + during this call - TODO ... + */ +#endif + return; + } + + const auto argc = parameterCount(); + + auto types = static_cast< int* >( malloc( argc * sizeof( int ) ) ); + auto arguments = static_cast< void** >( malloc( argc * sizeof( void* ) ) ); + + types[0] = QMetaType::UnknownType; // a return type is not possible + arguments[0] = nullptr; + + for ( uint i = 1; i < argc; i++ ) + { + if ( argv[i] == nullptr ) + { + Q_ASSERT( arguments[i] != nullptr ); + + free( types ); + free( arguments ); + + return; + } + + types[i] = m_parameterTypes[i - 1]; + arguments[i] = QMetaType::create( m_parameterTypes[i - 1], argv[i] ); + } + + if ( connectionType == Qt::QueuedConnection ) + { + qskInvokeFunctionQueued( object, m_invokable, argc, types, arguments ); + } + else // Qt::BlockingQueuedConnection ??? + { + QSemaphore semaphore; + + qskInvokeFunctionQueued( object, + m_invokable, argc, types, arguments, &semaphore ); + + semaphore.acquire(); + } } } diff --git a/src/common/QskMetaFunction.h b/src/common/QskMetaFunction.h index 13a7369b..9185ada7 100644 --- a/src/common/QskMetaFunction.h +++ b/src/common/QskMetaFunction.h @@ -7,10 +7,27 @@ #define QSK_META_FUNCTION_H 1 #include "QskGlobal.h" -#include "QskMetaCall.h" +#include "QskMetaInvokable.h" #include +namespace QskMetaFunctionTraits +{ + using namespace QtPrivate; + + template< typename T > + using IsMemberFunction = typename std::enable_if< FunctionPointer< T >::IsPointerToMemberFunction, + std::true_type >::type; + + template< typename T > + using IsFunction = typename std::enable_if< !FunctionPointer< T >::IsPointerToMemberFunction + && FunctionPointer< T >::ArgumentCount >= 0, std::true_type >::type; + + template< typename T > + using IsFunctor = typename std::enable_if< !FunctionPointer< T >::IsPointerToMemberFunction + && FunctionPointer< T >::ArgumentCount == -1, std::true_type >::type; +} + class QSK_EXPORT QskMetaFunction { Q_GADGET @@ -37,13 +54,13 @@ public: QskMetaFunction( const QskMetaFunction& ); QskMetaFunction( QskMetaFunction&& ); - template< typename T, QskMetaCall::IsMemberFunction< T >* = nullptr > + template< typename T, QskMetaFunctionTraits::IsMemberFunction< T >* = nullptr > QskMetaFunction( T ); - template< typename T, QskMetaCall::IsFunction< T >* = nullptr > + template< typename T, QskMetaFunctionTraits::IsFunction< T >* = nullptr > QskMetaFunction( T ); - template< typename T, QskMetaCall::IsFunctor< T >* = nullptr > + template< typename T, QskMetaFunctionTraits::IsFunctor< T >* = nullptr > QskMetaFunction( T ); ~QskMetaFunction(); @@ -62,44 +79,42 @@ public: Type functionType() const; private: - void init( QskMetaCall::Invokable*, const int* ); + void init( QskMetaInvokable*, const int* ); - QskMetaCall::Invokable* m_invokable; + QskMetaInvokable* m_invokable; const int* m_parameterTypes; }; -template< typename T, QskMetaCall::IsMemberFunction< T >* > +template< typename T, QskMetaFunctionTraits::IsMemberFunction< T >* > inline QskMetaFunction::QskMetaFunction( T function ) { using namespace QtPrivate; - using namespace QskMetaCall; using Traits = FunctionPointer< T >; const int Argc = Traits::ArgumentCount; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; - init( new MemberFunctionInvokable< T, Args, void >( function ), + init( new QskMetaMemberInvokable< T, Args, void >( function ), ConnectionTypes< typename Traits::Arguments >::types() ); } -template< typename T, QskMetaCall::IsFunction< T >* > +template< typename T, QskMetaFunctionTraits::IsFunction< T >* > inline QskMetaFunction::QskMetaFunction( T function ) { using namespace QtPrivate; - using namespace QskMetaCall; using Traits = FunctionPointer< T >; const int Argc = Traits::ArgumentCount; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; - init( new FunctionInvokable< T, Args, void >( function ), + init( new QskMetaFunctionInvokable< T, Args, void >( function ), ConnectionTypes< typename Traits::Arguments >::types() ); } -template< typename T, QskMetaCall::IsFunctor< T >* > +template< typename T, QskMetaFunctionTraits::IsFunctor< T >* > inline QskMetaFunction::QskMetaFunction( T functor ) { using namespace QtPrivate; @@ -109,7 +124,7 @@ inline QskMetaFunction::QskMetaFunction( T functor ) const int Argc = Traits::ArgumentCount; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; - init( new QskMetaCall::FunctorInvokable< T, Argc, Args, void > ( functor ), + init( new QskMetaFunctorInvokable< T, Argc, Args, void > ( functor ), ConnectionTypes< typename Traits::Arguments >::types() ); } diff --git a/src/common/QskMetaInvokable.cpp b/src/common/QskMetaInvokable.cpp new file mode 100644 index 00000000..90a3eed5 --- /dev/null +++ b/src/common/QskMetaInvokable.cpp @@ -0,0 +1,37 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#include "QskMetaInvokable.h" + +namespace +{ + // to have access to the private section of QSlotObjectBase + struct SlotObject + { + QAtomicInt ref; + QskMetaInvokable::InvokeFunction invoke; + }; + + static_assert( sizeof( SlotObject ) == sizeof( QskMetaInvokable ), + "Bad cast: QskMetaInvokable does not match" ); +} + +int QskMetaInvokable::typeInfo() const +{ + auto that = const_cast< QskMetaInvokable* >( this ); + + int value; + + reinterpret_cast< SlotObject* >( that )->invoke( TypeInfo, that, + nullptr, reinterpret_cast< void** >( &value ), nullptr ); + + return value; +} + +int QskMetaInvokable::refCount() const +{ + auto that = const_cast< QskMetaInvokable* >( this ); + return reinterpret_cast< SlotObject* >( that )->ref.load(); +} diff --git a/src/common/QskMetaInvokable.h b/src/common/QskMetaInvokable.h new file mode 100644 index 00000000..8465268c --- /dev/null +++ b/src/common/QskMetaInvokable.h @@ -0,0 +1,167 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#ifndef QSK_META_INVOKABLE_H +#define QSK_META_INVOKABLE_H 1 + +#include "QskGlobal.h" +#include + +// helper classes for QskMetaFunction + +class QskMetaInvokable : public QtPrivate::QSlotObjectBase +{ +public: + typedef void (* InvokeFunction)( + int which, QtPrivate::QSlotObjectBase*, QObject*, void**, bool* ); + + enum { TypeInfo = NumOperations + 1 }; + + int typeInfo() const; + int refCount() const; + +protected: + explicit QskMetaInvokable( InvokeFunction f ): + QSlotObjectBase( f ) + { + } +}; + +template< typename Func, typename Args, typename R > +class QskMetaFunctionInvokable : public QskMetaInvokable +{ +public: + typedef QtPrivate::FunctionPointer< Func > FuncType; + + explicit QskMetaFunctionInvokable( Func f ): + QskMetaInvokable( &invoke ), + function(f) + { + } + + static void invoke(int which, QtPrivate::QSlotObjectBase* invokable, + QObject* object, void** args, bool* ) + { + auto f = static_cast< QskMetaFunctionInvokable* >( invokable ); + + switch ( which ) + { + case Destroy: + { + delete f; + break; + } + case Call: + { + FuncType::template call< Args, R >( f->function, object, args ); + break; + } + case TypeInfo: + { + int* typeInfo = reinterpret_cast< int* >( args ); + *typeInfo = 1; // = QskMetaFunction::Function + + break; + } + } + } + + Func function; +}; + +template< typename Func, typename Args, typename R > +class QskMetaMemberInvokable : public QskMetaInvokable +{ +public: + explicit QskMetaMemberInvokable( Func f ): + QskMetaInvokable( &invoke ), + function(f) + { + } + + static void invoke( int which, QtPrivate::QSlotObjectBase* invokable, + QObject* object, void** args, bool* ret ) + { + typedef QtPrivate::FunctionPointer< Func > FuncType; + + auto f = static_cast< QskMetaMemberInvokable* >( invokable ); + + switch (which) + { + case Destroy: + { + delete f; + break; + } + case Call: + { + FuncType::template call< Args, R >( + f->function, static_cast< typename FuncType::Object* >( object ), args ); + + break; + } + case Compare: + { + *ret = *reinterpret_cast< Func* >( args ) == f->function; + break; + } + case TypeInfo: + { + int* typeInfo = reinterpret_cast< int* >( args ); + *typeInfo = 0; // = QskMetaFunction::Member + + break; + } + } + } + +private: + Func function; +}; + +template< typename Func, int N, typename Args, typename R > +class QskMetaFunctorInvokable : public QskMetaInvokable +{ +public: + typedef QtPrivate::Functor< Func, N > FuncType; + + explicit QskMetaFunctorInvokable( Func f ): + QskMetaInvokable( &invoke ), + function( std::move( f ) ) + { + } + + static void invoke( int which, QSlotObjectBase* invokable, + QObject* object, void** args, bool* ) + { + auto f = static_cast< QskMetaFunctorInvokable* >( invokable ); + + switch (which) + { + case Destroy: + { + delete f; + break; + } + case Call: + { + FuncType::template call< Args, R >( f->function, object, args ); + break; + } + case TypeInfo: + { + int* typeInfo = reinterpret_cast< int* >( args ); + *typeInfo = 2; // QskMetaFunction::Functor; + + break; + } + } + } + +private: + Func function; +}; + +#endif diff --git a/src/src.pro b/src/src.pro index 777c3a03..66c56e2d 100644 --- a/src/src.pro +++ b/src/src.pro @@ -40,9 +40,9 @@ HEADERS += \ common/QskGlobal.h \ common/QskGradient.h \ common/QskMargins.h \ - common/QskMetaCall.h \ common/QskMetaCallback.h \ common/QskMetaFunction.h \ + common/QskMetaInvokable.cpp \ common/QskModule.h \ common/QskNamespace.h \ common/QskObjectCounter.h \ @@ -59,9 +59,9 @@ SOURCES += \ common/QskFunctions.cpp \ common/QskGradient.cpp \ common/QskMargins.cpp \ - common/QskMetaCall.cpp \ common/QskMetaCallback.cpp \ common/QskMetaFunction.cpp \ + common/QskMetaInvokable.cpp \ common/QskModule.cpp \ common/QskObjectCounter.cpp \ common/QskSizePolicy.cpp \