2018-02-28 09:43:15 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* 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 <QObject>
|
|
|
|
|
|
|
|
// helper classes for QskMetaFunction
|
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
#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
|
2018-02-28 09:43:15 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef void (* InvokeFunction)(
|
|
|
|
int which, QtPrivate::QSlotObjectBase*, QObject*, void**, bool* );
|
|
|
|
|
|
|
|
enum { TypeInfo = NumOperations + 1 };
|
|
|
|
|
|
|
|
int typeInfo() const;
|
|
|
|
int refCount() const;
|
|
|
|
|
|
|
|
protected:
|
2018-02-28 15:48:46 +00:00
|
|
|
friend class QskMetaFunction;
|
|
|
|
|
2018-02-28 09:43:15 +00:00
|
|
|
explicit QskMetaInvokable( InvokeFunction f ):
|
|
|
|
QSlotObjectBase( f )
|
|
|
|
{
|
|
|
|
}
|
2018-02-28 15:48:46 +00:00
|
|
|
|
|
|
|
#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
|
2018-02-28 09:43:15 +00:00
|
|
|
};
|
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
template< typename Function, typename Args, typename R >
|
2018-02-28 09:43:15 +00:00
|
|
|
class QskMetaFunctionInvokable : public QskMetaInvokable
|
|
|
|
{
|
|
|
|
public:
|
2018-02-28 15:48:46 +00:00
|
|
|
typedef QtPrivate::FunctionPointer< Function > FuncType;
|
2018-02-28 09:43:15 +00:00
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
explicit QskMetaFunctionInvokable( Function function ):
|
2018-02-28 09:43:15 +00:00
|
|
|
QskMetaInvokable( &invoke ),
|
2018-02-28 15:48:46 +00:00
|
|
|
m_function( function )
|
2018-02-28 09:43:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void invoke(int which, QtPrivate::QSlotObjectBase* invokable,
|
|
|
|
QObject* object, void** args, bool* )
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
auto invokableFunction = static_cast< QskMetaFunctionInvokable* >( invokable );
|
2018-02-28 09:43:15 +00:00
|
|
|
|
|
|
|
switch ( which )
|
|
|
|
{
|
|
|
|
case Destroy:
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
#if QSK_SHARE_INVOKABLES
|
|
|
|
remove( typeid( Function ) );
|
|
|
|
#endif
|
|
|
|
delete invokableFunction;
|
|
|
|
|
2018-02-28 09:43:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Call:
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
FuncType::template call< Args, R >(
|
|
|
|
invokableFunction->m_function, object, args );
|
2018-02-28 09:43:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TypeInfo:
|
|
|
|
{
|
|
|
|
int* typeInfo = reinterpret_cast< int* >( args );
|
|
|
|
*typeInfo = 1; // = QskMetaFunction::Function
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
Function m_function;
|
2018-02-28 09:43:15 +00:00
|
|
|
};
|
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
template< typename Function, typename Args, typename R >
|
2018-02-28 09:43:15 +00:00
|
|
|
class QskMetaMemberInvokable : public QskMetaInvokable
|
|
|
|
{
|
|
|
|
public:
|
2018-02-28 15:48:46 +00:00
|
|
|
explicit QskMetaMemberInvokable( Function function ):
|
2018-02-28 09:43:15 +00:00
|
|
|
QskMetaInvokable( &invoke ),
|
2018-02-28 15:48:46 +00:00
|
|
|
m_function( function )
|
2018-02-28 09:43:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void invoke( int which, QtPrivate::QSlotObjectBase* invokable,
|
|
|
|
QObject* object, void** args, bool* ret )
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
typedef QtPrivate::FunctionPointer< Function > FuncType;
|
2018-02-28 09:43:15 +00:00
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
auto invokableMember = static_cast< QskMetaMemberInvokable* >( invokable );
|
2018-02-28 09:43:15 +00:00
|
|
|
|
|
|
|
switch (which)
|
|
|
|
{
|
|
|
|
case Destroy:
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
#if QSK_SHARE_INVOKABLES
|
|
|
|
remove( typeid( Function ) );
|
|
|
|
#endif
|
|
|
|
delete invokableMember;
|
|
|
|
|
2018-02-28 09:43:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Call:
|
|
|
|
{
|
|
|
|
FuncType::template call< Args, R >(
|
2018-02-28 15:48:46 +00:00
|
|
|
invokableMember->m_function,
|
|
|
|
static_cast< typename FuncType::Object* >( object ), args );
|
2018-02-28 09:43:15 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Compare:
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
const auto function = *reinterpret_cast< Function* >( args );
|
|
|
|
*ret = function == invokableMember->m_function;
|
2018-02-28 09:43:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TypeInfo:
|
|
|
|
{
|
|
|
|
int* typeInfo = reinterpret_cast< int* >( args );
|
|
|
|
*typeInfo = 0; // = QskMetaFunction::Member
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-02-28 15:48:46 +00:00
|
|
|
Function m_function;
|
2018-02-28 09:43:15 +00:00
|
|
|
};
|
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
template< typename Function, int N, typename Args, typename R >
|
2018-02-28 09:43:15 +00:00
|
|
|
class QskMetaFunctorInvokable : public QskMetaInvokable
|
|
|
|
{
|
|
|
|
public:
|
2018-02-28 15:48:46 +00:00
|
|
|
typedef QtPrivate::Functor< Function, N > FuncType;
|
2018-02-28 09:43:15 +00:00
|
|
|
|
2018-02-28 15:48:46 +00:00
|
|
|
explicit QskMetaFunctorInvokable( Function function ):
|
2018-02-28 09:43:15 +00:00
|
|
|
QskMetaInvokable( &invoke ),
|
2018-02-28 15:48:46 +00:00
|
|
|
m_function( std::move( function ) )
|
2018-02-28 09:43:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void invoke( int which, QSlotObjectBase* invokable,
|
|
|
|
QObject* object, void** args, bool* )
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
auto invokableFunctor = static_cast< QskMetaFunctorInvokable* >( invokable );
|
2018-02-28 09:43:15 +00:00
|
|
|
|
|
|
|
switch (which)
|
|
|
|
{
|
|
|
|
case Destroy:
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
#if QSK_SHARE_INVOKABLES
|
|
|
|
remove( typeid( Function ) );
|
|
|
|
#endif
|
|
|
|
delete invokableFunctor;
|
|
|
|
|
2018-02-28 09:43:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Call:
|
|
|
|
{
|
2018-02-28 15:48:46 +00:00
|
|
|
FuncType::template call< Args, R >(
|
|
|
|
invokableFunctor->m_function, object, args );
|
2018-02-28 09:43:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TypeInfo:
|
|
|
|
{
|
|
|
|
int* typeInfo = reinterpret_cast< int* >( args );
|
|
|
|
*typeInfo = 2; // QskMetaFunction::Functor;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-02-28 15:48:46 +00:00
|
|
|
Function m_function;
|
2018-02-28 09:43:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|