qskinny/src/common/QskMetaInvokable.h

213 lines
5.5 KiB
C
Raw Normal View History

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