[Misc] QskMeta classes improved
This commit is contained in:
parent
02639e5d04
commit
3079698d63
|
@ -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<Invokable>( 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<Invokable>( 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<Invokable>( 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 )
|
||||
|
|
|
@ -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 <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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue