QskMeta classes improved

This commit is contained in:
Uwe Rathmann 2018-02-28 16:48:46 +01:00
parent 0075ccbdbd
commit 02639e5d04
6 changed files with 336 additions and 108 deletions

View File

@ -4,11 +4,13 @@
*****************************************************************************/ *****************************************************************************/
#include "QskMetaCallback.h" #include "QskMetaCallback.h"
#include "QskMetaFunction.h"
#include <QObject> #include <QObject>
#include <QCoreApplication> #include <QCoreApplication>
#include <QThread> #include <QThread>
#include <QSemaphore> #include <QSemaphore>
#include <QMetaMethod>
QSK_QT_PRIVATE_BEGIN QSK_QT_PRIVATE_BEGIN
#include <private/qobject_p.h> #include <private/qobject_p.h>
@ -31,42 +33,49 @@ static inline void qskInvokeMethodQueued( QObject* object,
QskMetaCallback::QskMetaCallback( const QObject* object, QskMetaCallback::QskMetaCallback( const QObject* object,
const QMetaMethod& method, Qt::ConnectionType connectionType ): const QMetaMethod& method, Qt::ConnectionType connectionType ):
m_object( const_cast< QObject* >( object ) ), m_object( const_cast< QObject* >( object ) ),
m_method( new QMetaMethod( method ) ), m_methodData { method.enclosingMetaObject(), method.methodIndex() },
m_type( MetaMethod ), m_type( MetaMethod ),
m_connectionType( static_cast< ushort >( connectionType & ~Qt::UniqueConnection ) ) m_hasObject( object != nullptr ),
m_connectionType( static_cast< ushort >( connectionType & 0x3 ) )
{ {
} }
QskMetaCallback::QskMetaCallback( const QObject* object, QskMetaCallback::QskMetaCallback( const QObject* object,
const QskMetaFunction& function, Qt::ConnectionType connectionType ): const QskMetaFunction& function, Qt::ConnectionType connectionType ):
m_object( const_cast< QObject* >( object ) ), m_object( const_cast< QObject* >( object ) ),
m_function( new QskMetaFunction( function ) ), m_functionData { function.invokable(), function.parameterTypes() },
m_type( MetaFunction ), m_type( MetaFunction ),
m_hasObject( object != nullptr ),
m_connectionType( static_cast< ushort >( connectionType & ~Qt::UniqueConnection ) ) m_connectionType( static_cast< ushort >( connectionType & ~Qt::UniqueConnection ) )
{ {
if ( m_functionData.invokable )
m_functionData.invokable->ref();
} }
QskMetaCallback::QskMetaCallback( const QskMetaCallback& other ): QskMetaCallback::QskMetaCallback( const QskMetaCallback& other ):
m_object( other.m_object ), m_object( other.m_object ),
m_function(), m_type( other.m_type ),
m_type( Invalid ), m_hasObject( other.m_hasObject ),
m_connectionType( other.m_connectionType ) m_connectionType( other.m_connectionType )
{ {
if ( other.m_type != m_type )
{
reset();
m_type = other.m_type;
}
switch( m_type ) switch( m_type )
{ {
case MetaMethod: case MetaMethod:
m_method = new QMetaMethod( *other.m_method ); {
break; m_methodData.metaObject = other.m_methodData.metaObject;
m_methodData.methodIndex = other.m_methodData.methodIndex;
case MetaFunction:
m_function = new QskMetaFunction( *other.m_function );
break; break;
}
case MetaFunction:
{
m_functionData.invokable = other.m_functionData.invokable;
if ( m_functionData.invokable )
m_functionData.invokable->ref();
m_functionData.parameterTypes = other.m_functionData.parameterTypes;
break;
}
default: default:
break; break;
@ -75,31 +84,82 @@ QskMetaCallback::QskMetaCallback( const QskMetaCallback& other ):
QskMetaCallback::~QskMetaCallback() QskMetaCallback::~QskMetaCallback()
{ {
reset(); if ( ( m_type == MetaFunction ) && m_functionData.invokable )
m_functionData.invokable->destroyIfLastRef();
} }
QskMetaCallback& QskMetaCallback::operator=( const QskMetaCallback& other ) QskMetaCallback& QskMetaCallback::operator=( const QskMetaCallback& other )
{ {
m_object = other.m_object; m_object = other.m_object;
m_hasObject = other.m_hasObject;
m_connectionType = other.m_connectionType; m_connectionType = other.m_connectionType;
if ( other.m_type != m_type ) switch( other.m_type )
{ {
reset(); case MetaMethod:
m_type = other.m_type; {
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;
break;
}
case MetaFunction:
{
if ( ( m_type == MetaFunction ) && m_functionData.invokable )
m_functionData.invokable->destroyIfLastRef();
m_functionData.invokable = other.m_functionData.invokable;
if ( m_functionData.invokable )
m_functionData.invokable->ref();
m_functionData.parameterTypes = other.m_functionData.parameterTypes;
break;
} }
if ( other.m_type != Invalid ) default:
{ if ( ( m_type == MetaFunction ) && m_functionData.invokable )
if ( other.m_type == MetaMethod ) m_functionData.invokable->destroyIfLastRef();
m_method = new QMetaMethod( *other.m_method );
else
m_function = new QskMetaFunction( *other.m_function );
} }
m_type = other.m_type;
return *this; return *this;
} }
bool QskMetaCallback::isValid() const
{
if ( m_hasObject && m_object.isNull() )
return false;
switch( m_type )
{
case MetaMethod:
{
const auto& d = m_methodData;
if ( d.metaObject && ( d.methodIndex >= 0 )
&& ( d.methodIndex < d.metaObject->methodCount() ) )
{
return true;
}
return false;
}
case MetaFunction:
{
return m_functionData.invokable != nullptr;
}
default:
return false;
}
}
void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType ) void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType )
{ {
m_connectionType = connectionType; m_connectionType = connectionType;
@ -107,22 +167,13 @@ void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType )
void QskMetaCallback::reset() void QskMetaCallback::reset()
{ {
switch( m_type ) m_object = nullptr;
{ m_hasObject = false;
case MetaMethod:
delete m_method;
m_method = nullptr;
break;
case MetaFunction: if ( m_type == MetaFunction && m_functionData.invokable )
delete m_function; m_functionData.invokable->destroyIfLastRef();
m_function = nullptr;
break;
default:
break;
}
m_functionData = { nullptr, nullptr }; // for the debugger
m_type = Invalid; m_type = Invalid;
} }
@ -134,17 +185,25 @@ QVector< int > QskMetaCallback::parameterTypes() const
{ {
case MetaMethod: case MetaMethod:
{ {
const int paramCount = m_method->parameterCount(); const auto& d = m_methodData;
if ( m_methodData.metaObject )
{
#if 1
// should be doable without QMetaMethod. TODO ...
const auto method = d.metaObject->method( d.methodIndex );
#endif
const int paramCount = method.parameterCount();
paramTypes.reserve( paramCount ); paramTypes.reserve( paramCount );
for ( int i = 0; i < paramCount; i++ ) for ( int i = 0; i < paramCount; i++ )
paramTypes += m_method->parameterType( i ); paramTypes += method.parameterType( i );
}
break; break;
} }
case MetaFunction: case MetaFunction:
{ {
auto types = m_function->parameterTypes(); auto types = m_functionData.parameterTypes;
if ( types ) if ( types )
{ {
while ( *types ) while ( *types )
@ -162,18 +221,25 @@ QVector< int > QskMetaCallback::parameterTypes() const
void QskMetaCallback::invoke( void* args[] ) void QskMetaCallback::invoke( void* args[] )
{ {
if ( !isValid() )
return;
auto object = const_cast< QObject* >( m_object.data() ); auto object = const_cast< QObject* >( m_object.data() );
switch( m_type ) switch( m_type )
{ {
case MetaMethod: case MetaMethod:
{ {
qskInvokeMethod( object, *m_method, args, connectionType() ); qskInvokeMethod( object, m_methodData.metaObject,
m_methodData.methodIndex, args, connectionType() );
break; break;
} }
case MetaFunction: case MetaFunction:
{ {
m_function->invoke( object, args, connectionType() ); QskMetaFunction function( m_functionData.invokable, m_functionData.parameterTypes );
function.invoke( object, args, connectionType() );
break; break;
} }
@ -182,30 +248,54 @@ void QskMetaCallback::invoke( void* args[] )
} }
} }
void qskInvokeMethod( QObject* object, void qskInvokeMethod( QObject* object,
const QMetaMethod& method, void* args[], const QMetaMethod& method, void* args[],
Qt::ConnectionType connectionType ) Qt::ConnectionType connectionType )
{ {
if ( object == nullptr ) auto metaObject = method.enclosingMetaObject();
if ( metaObject == nullptr )
return; return;
auto metaObject = method.enclosingMetaObject(); const int methodIndex = method.methodIndex() - metaObject->methodOffset();
qskInvokeMethod( object, metaObject, methodIndex, args, connectionType );
}
const int methodOffset = metaObject->methodOffset(); void qskInvokeMethod( QObject* object,
const int methodIndex = method.methodIndex() - methodOffset; const QMetaObject* metaObject, int methodIndex, void* args[],
Qt::ConnectionType connectionType )
if ( connectionType == Qt::AutoConnection ) {
if ( ( metaObject == nullptr ) || ( methodIndex < 0 )
|| ( methodIndex > metaObject->methodCount() ) )
{ {
connectionType = ( object->thread() == QThread::currentThread() ) return;
? Qt::DirectConnection : Qt::QueuedConnection;
} }
if ( connectionType == Qt::DirectConnection ) int invokeType = connectionType & 0x3;
if ( invokeType == Qt::AutoConnection )
{ {
invokeType = ( object && object->thread() != QThread::currentThread() )
? Qt::QueuedConnection : Qt::DirectConnection;
}
else if ( invokeType == Qt::BlockingQueuedConnection )
{
if ( ( object == nullptr ) || object->thread() == QThread::currentThread() )
{
// We would end up in a deadlock, better do nothing
return;
}
}
if ( invokeType == Qt::DirectConnection )
{
#if 1
if ( object == nullptr )
return; // do we really need an object here ???
#endif
if ( metaObject->d.static_metacall ) if ( metaObject->d.static_metacall )
{ {
metaObject->d.static_metacall(object, metaObject->d.static_metacall( object,
QMetaObject::InvokeMetaMethod, methodIndex, args ); QMetaObject::InvokeMetaMethod, methodIndex, args );
} }
else else
@ -216,6 +306,13 @@ void qskInvokeMethod( QObject* object,
} }
else else
{ {
if ( object == nullptr )
return;
#if 1
// should be doable without QMetaMethod. TODO ...
const auto method = metaObject->method( methodIndex );
#endif
const int paramCount = method.parameterCount(); const int paramCount = method.parameterCount();
auto types = static_cast< int* >( malloc( paramCount * sizeof( int ) ) ); auto types = static_cast< int* >( malloc( paramCount * sizeof( int ) ) );

View File

@ -7,13 +7,14 @@
#define QSK_META_CALLBACK_H 1 #define QSK_META_CALLBACK_H 1
#include "QskGlobal.h" #include "QskGlobal.h"
#include "QskMetaFunction.h"
#include <QObject>
#include <QPointer> #include <QPointer>
#include <QMetaMethod>
#include <QVector> #include <QVector>
class QskMetaInvokable;
class QskMetaFunction;
class QMetaMethod;
class QskMetaCallback class QskMetaCallback
{ {
public: public:
@ -59,26 +60,35 @@ private:
QPointer< const QObject > m_object; QPointer< const QObject > m_object;
struct FunctionData
{
QskMetaInvokable* invokable;
const int* parameterTypes;
};
struct MethodData
{
const QMetaObject* metaObject;
int methodIndex;
};
union union
{ {
QskMetaFunction* m_function; FunctionData m_functionData;
QMetaMethod* m_method; MethodData m_methodData;
}; };
int m_type : 3; int m_type : 3;
bool m_hasObject : 1;
ushort m_connectionType : 3; ushort m_connectionType : 3;
}; };
inline QskMetaCallback::QskMetaCallback(): inline QskMetaCallback::QskMetaCallback():
m_type( Invalid ) m_type( Invalid ),
m_hasObject( false )
{ {
} }
inline bool QskMetaCallback::isValid() const
{
return m_type > 0;
}
inline QskMetaCallback::Type QskMetaCallback::type() const inline QskMetaCallback::Type QskMetaCallback::type() const
{ {
return static_cast< Type >( m_type ); return static_cast< Type >( m_type );
@ -93,6 +103,10 @@ QSK_EXPORT void qskInvokeMethod(
QObject* object, const QMetaMethod&, void* args[], QObject* object, const QMetaMethod&, void* args[],
Qt::ConnectionType = Qt::AutoConnection ); Qt::ConnectionType = Qt::AutoConnection );
QSK_EXPORT void qskInvokeMethod(
QObject* object, const QMetaObject*, int methodIndex, void* args[],
Qt::ConnectionType = Qt::AutoConnection );
Q_DECLARE_METATYPE( QskMetaCallback ) Q_DECLARE_METATYPE( QskMetaCallback )
#endif #endif

View File

@ -34,6 +34,15 @@ QskMetaFunction::QskMetaFunction():
{ {
} }
QskMetaFunction::QskMetaFunction(
QskMetaInvokable* invokable, const int* parameterTypes ):
m_invokable( invokable ),
m_parameterTypes( parameterTypes )
{
if ( m_invokable )
m_invokable->ref();
}
QskMetaFunction::QskMetaFunction( const QskMetaFunction& other ): QskMetaFunction::QskMetaFunction( const QskMetaFunction& other ):
m_invokable( other.m_invokable ), m_invokable( other.m_invokable ),
m_parameterTypes( other.m_parameterTypes ) m_parameterTypes( other.m_parameterTypes )
@ -96,11 +105,6 @@ void QskMetaFunction::init( QskMetaInvokable* invokable,
m_parameterTypes = parameterTypes; m_parameterTypes = parameterTypes;
} }
const int* QskMetaFunction::parameterTypes() const
{
return m_parameterTypes;
}
size_t QskMetaFunction::parameterCount() const size_t QskMetaFunction::parameterCount() const
{ {
if ( m_parameterTypes ) if ( m_parameterTypes )
@ -134,12 +138,12 @@ void QskMetaFunction::invoke(
if ( invokeType == Qt::AutoConnection ) if ( invokeType == Qt::AutoConnection )
{ {
invokeType = ( object->thread() == QThread::currentThread() ) invokeType = ( object && object->thread() != QThread::currentThread() )
? Qt::DirectConnection : Qt::QueuedConnection; ? Qt::QueuedConnection : Qt::DirectConnection;
} }
else if ( invokeType == Qt::BlockingQueuedConnection ) else if ( invokeType == Qt::BlockingQueuedConnection )
{ {
if ( object->thread() == QThread::currentThread() ) if ( ( object == nullptr ) || object->thread() == QThread::currentThread() )
{ {
// We would end up in a deadlock, better do nothing // We would end up in a deadlock, better do nothing
return; return;
@ -202,3 +206,5 @@ void QskMetaFunction::invoke(
} }
} }
} }
#include "moc_QskMetaFunction.cpp"

View File

@ -78,13 +78,51 @@ public:
Type functionType() const; Type functionType() const;
private: protected:
friend class QskMetaCallback;
QskMetaFunction( QskMetaInvokable*, const int* );
void init( QskMetaInvokable*, const int* ); void init( QskMetaInvokable*, const int* );
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; QskMetaInvokable* m_invokable;
const int* m_parameterTypes; const int* m_parameterTypes;
}; };
inline QskMetaInvokable* QskMetaFunction::invokable() const
{
return m_invokable;
}
inline const int* QskMetaFunction::parameterTypes() const
{
return m_parameterTypes;
}
template< typename T, QskMetaFunctionTraits::IsMemberFunction< T >* > template< typename T, QskMetaFunctionTraits::IsMemberFunction< T >* >
inline QskMetaFunction::QskMetaFunction( T function ) inline QskMetaFunction::QskMetaFunction( T function )
@ -95,8 +133,9 @@ inline QskMetaFunction::QskMetaFunction( T function )
const int Argc = Traits::ArgumentCount; const int Argc = Traits::ArgumentCount;
using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
using Invokable = QskMetaMemberInvokable< T, Args, void >;
init( new QskMetaMemberInvokable< T, Args, void >( function ), init( findInvokable<Invokable>( function ),
ConnectionTypes< typename Traits::Arguments >::types() ); ConnectionTypes< typename Traits::Arguments >::types() );
} }
@ -109,8 +148,9 @@ inline QskMetaFunction::QskMetaFunction( T function )
const int Argc = Traits::ArgumentCount; const int Argc = Traits::ArgumentCount;
using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
using Invokable = QskMetaFunctionInvokable< T, Args, void >;
init( new QskMetaFunctionInvokable< T, Args, void >( function ), init( findInvokable<Invokable>( function ),
ConnectionTypes< typename Traits::Arguments >::types() ); ConnectionTypes< typename Traits::Arguments >::types() );
} }
@ -123,8 +163,9 @@ inline QskMetaFunction::QskMetaFunction( T functor )
const int Argc = Traits::ArgumentCount; const int Argc = Traits::ArgumentCount;
using Args = typename List_Left< typename Traits::Arguments, Argc >::Value; using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
using Invokable = QskMetaFunctorInvokable< T, Argc, Args, void >;
init( new QskMetaFunctorInvokable< T, Argc, Args, void > ( functor ), init( findInvokable<Invokable>( functor ),
ConnectionTypes< typename Traits::Arguments >::types() ); ConnectionTypes< typename Traits::Arguments >::types() );
} }

View File

@ -35,3 +35,28 @@ int QskMetaInvokable::refCount() const
auto that = const_cast< QskMetaInvokable* >( this ); auto that = const_cast< QskMetaInvokable* >( this );
return reinterpret_cast< SlotObject* >( that )->ref.load(); return reinterpret_cast< SlotObject* >( that )->ref.load();
} }
#if QSK_SHARED_META_INVOKABLE
#include <unordered_map>
#include <typeindex>
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

View File

@ -11,7 +11,22 @@
// helper classes for QskMetaFunction // helper classes for QskMetaFunction
class QskMetaInvokable : public QtPrivate::QSlotObjectBase #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: public:
typedef void (* InvokeFunction)( typedef void (* InvokeFunction)(
@ -23,39 +38,58 @@ public:
int refCount() const; int refCount() const;
protected: protected:
friend class QskMetaFunction;
explicit QskMetaInvokable( InvokeFunction f ): explicit QskMetaInvokable( InvokeFunction f ):
QSlotObjectBase( 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 Func, typename Args, typename R > template< typename Function, typename Args, typename R >
class QskMetaFunctionInvokable : public QskMetaInvokable class QskMetaFunctionInvokable : public QskMetaInvokable
{ {
public: public:
typedef QtPrivate::FunctionPointer< Func > FuncType; typedef QtPrivate::FunctionPointer< Function > FuncType;
explicit QskMetaFunctionInvokable( Func f ): explicit QskMetaFunctionInvokable( Function function ):
QskMetaInvokable( &invoke ), QskMetaInvokable( &invoke ),
function(f) m_function( function )
{ {
} }
static void invoke(int which, QtPrivate::QSlotObjectBase* invokable, static void invoke(int which, QtPrivate::QSlotObjectBase* invokable,
QObject* object, void** args, bool* ) QObject* object, void** args, bool* )
{ {
auto f = static_cast< QskMetaFunctionInvokable* >( invokable ); auto invokableFunction = static_cast< QskMetaFunctionInvokable* >( invokable );
switch ( which ) switch ( which )
{ {
case Destroy: case Destroy:
{ {
delete f; #if QSK_SHARE_INVOKABLES
remove( typeid( Function ) );
#endif
delete invokableFunction;
break; break;
} }
case Call: case Call:
{ {
FuncType::template call< Args, R >( f->function, object, args ); FuncType::template call< Args, R >(
invokableFunction->m_function, object, args );
break; break;
} }
case TypeInfo: case TypeInfo:
@ -68,43 +102,49 @@ public:
} }
} }
Func function; Function m_function;
}; };
template< typename Func, typename Args, typename R > template< typename Function, typename Args, typename R >
class QskMetaMemberInvokable : public QskMetaInvokable class QskMetaMemberInvokable : public QskMetaInvokable
{ {
public: public:
explicit QskMetaMemberInvokable( Func f ): explicit QskMetaMemberInvokable( Function function ):
QskMetaInvokable( &invoke ), QskMetaInvokable( &invoke ),
function(f) m_function( function )
{ {
} }
static void invoke( int which, QtPrivate::QSlotObjectBase* invokable, static void invoke( int which, QtPrivate::QSlotObjectBase* invokable,
QObject* object, void** args, bool* ret ) QObject* object, void** args, bool* ret )
{ {
typedef QtPrivate::FunctionPointer< Func > FuncType; typedef QtPrivate::FunctionPointer< Function > FuncType;
auto f = static_cast< QskMetaMemberInvokable* >( invokable ); auto invokableMember = static_cast< QskMetaMemberInvokable* >( invokable );
switch (which) switch (which)
{ {
case Destroy: case Destroy:
{ {
delete f; #if QSK_SHARE_INVOKABLES
remove( typeid( Function ) );
#endif
delete invokableMember;
break; break;
} }
case Call: case Call:
{ {
FuncType::template call< Args, R >( FuncType::template call< Args, R >(
f->function, static_cast< typename FuncType::Object* >( object ), args ); invokableMember->m_function,
static_cast< typename FuncType::Object* >( object ), args );
break; break;
} }
case Compare: case Compare:
{ {
*ret = *reinterpret_cast< Func* >( args ) == f->function; const auto function = *reinterpret_cast< Function* >( args );
*ret = function == invokableMember->m_function;
break; break;
} }
case TypeInfo: case TypeInfo:
@ -118,36 +158,41 @@ public:
} }
private: private:
Func function; Function m_function;
}; };
template< typename Func, int N, typename Args, typename R > template< typename Function, int N, typename Args, typename R >
class QskMetaFunctorInvokable : public QskMetaInvokable class QskMetaFunctorInvokable : public QskMetaInvokable
{ {
public: public:
typedef QtPrivate::Functor< Func, N > FuncType; typedef QtPrivate::Functor< Function, N > FuncType;
explicit QskMetaFunctorInvokable( Func f ): explicit QskMetaFunctorInvokable( Function function ):
QskMetaInvokable( &invoke ), QskMetaInvokable( &invoke ),
function( std::move( f ) ) m_function( std::move( function ) )
{ {
} }
static void invoke( int which, QSlotObjectBase* invokable, static void invoke( int which, QSlotObjectBase* invokable,
QObject* object, void** args, bool* ) QObject* object, void** args, bool* )
{ {
auto f = static_cast< QskMetaFunctorInvokable* >( invokable ); auto invokableFunctor = static_cast< QskMetaFunctorInvokable* >( invokable );
switch (which) switch (which)
{ {
case Destroy: case Destroy:
{ {
delete f; #if QSK_SHARE_INVOKABLES
remove( typeid( Function ) );
#endif
delete invokableFunctor;
break; break;
} }
case Call: case Call:
{ {
FuncType::template call< Args, R >( f->function, object, args ); FuncType::template call< Args, R >(
invokableFunctor->m_function, object, args );
break; break;
} }
case TypeInfo: case TypeInfo:
@ -161,7 +206,7 @@ public:
} }
private: private:
Func function; Function m_function;
}; };
#endif #endif