implementation of QskMetaFunction continued - still several issues to
solve
This commit is contained in:
parent
1d086d9051
commit
28660cca7d
@ -13,12 +13,13 @@ Invoker::Invoker( QObject* parent ):
|
||||
void Invoker::addCallback( const QObject* object,
|
||||
const QskMetaFunction& function )
|
||||
{
|
||||
m_callbacks += QskMetaCallback( object, function, Qt::DirectConnection );
|
||||
m_callbacks += QskMetaCallback( object, function );
|
||||
}
|
||||
|
||||
void Invoker::invoke( qreal realValue, int intValue )
|
||||
void Invoker::invoke( qreal realValue, int intValue,
|
||||
Qt::ConnectionType connectionType )
|
||||
{
|
||||
for ( auto callback : qskAsConst( m_callbacks ) )
|
||||
for ( auto& callback : m_callbacks )
|
||||
{
|
||||
void* args[3] = { nullptr };
|
||||
|
||||
@ -44,6 +45,11 @@ void Invoker::invoke( qreal realValue, int intValue )
|
||||
}
|
||||
}
|
||||
|
||||
callback.invoke( args );
|
||||
callback.setConnectionType( connectionType );
|
||||
|
||||
if ( connectionType == Qt::DirectConnection )
|
||||
callback.invoke( args );
|
||||
else if ( callback.object() )
|
||||
callback.invoke( args );
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
void addCallback( const QskMetaFunction& );
|
||||
void addCallback( const QObject*, const QskMetaFunction& );
|
||||
|
||||
void invoke( qreal d, int i );
|
||||
void invoke( qreal d, int i, Qt::ConnectionType );
|
||||
|
||||
private:
|
||||
QVector< QskMetaCallback > m_callbacks;
|
||||
|
@ -4,7 +4,9 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Invoker.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
static void debugValueI( int i )
|
||||
{
|
||||
@ -47,8 +49,7 @@ public:
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
Q_UNUSED( argc )
|
||||
Q_UNUSED( argv )
|
||||
QCoreApplication app( argc, argv );
|
||||
|
||||
MyObject object;
|
||||
|
||||
@ -69,5 +70,14 @@ int main( int argc, char* argv[] )
|
||||
invoker.addCallback( []( int i ) { qDebug() << i; } );
|
||||
invoker.addCallback( []( double d ) { qDebug() << d; } );
|
||||
|
||||
invoker.invoke( 3.14, 35 );
|
||||
qDebug() << "== Direct Connections";
|
||||
invoker.invoke( 3.14, 35, Qt::DirectConnection );
|
||||
|
||||
qDebug() << "== Queued Connections";
|
||||
|
||||
QTimer::singleShot( 0,
|
||||
[&invoker] { invoker.invoke( 0.07, 42, Qt::QueuedConnection ); } );
|
||||
|
||||
QTimer::singleShot( 100, &app, QCoreApplication::quit );
|
||||
return app.exec();
|
||||
}
|
||||
|
@ -33,6 +33,46 @@ namespace QskMetaCall
|
||||
}
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
invokable->ref();
|
||||
}
|
||||
|
||||
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 )
|
||||
@ -66,22 +106,33 @@ void QskMetaCall::invoke( QObject* object,
|
||||
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; // return type
|
||||
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 );
|
||||
Q_ASSERT( args[i] != nullptr );
|
||||
arguments[i] = args[i - 1];
|
||||
}
|
||||
|
||||
Q_ASSERT( args[paramCount] == nullptr );
|
||||
|
||||
if ( connectionType == Qt::QueuedConnection )
|
||||
{
|
||||
QMetaCallEvent* event = new QMetaCallEvent(
|
||||
methodOffset, methodIndex, metaObject->d.static_metacall,
|
||||
nullptr, -1, paramCount + 1, types, args );
|
||||
auto event = new MethodCallEvent(
|
||||
metaObject, methodIndex, paramCount + 1, types, args );
|
||||
|
||||
QCoreApplication::postEvent(object, event );
|
||||
}
|
||||
@ -89,10 +140,8 @@ void QskMetaCall::invoke( QObject* object,
|
||||
{
|
||||
QSemaphore semaphore;
|
||||
|
||||
// what about argc + types ???
|
||||
auto event = new QMetaCallEvent(
|
||||
methodOffset, methodIndex, metaObject->d.static_metacall,
|
||||
nullptr, -1, 0, 0, args, &semaphore );
|
||||
auto event = new MethodCallEvent(
|
||||
metaObject, methodIndex, paramCount + 1, types, args, &semaphore );
|
||||
|
||||
QCoreApplication::postEvent( object, event );
|
||||
|
||||
@ -102,7 +151,7 @@ void QskMetaCall::invoke( QObject* object,
|
||||
}
|
||||
|
||||
void QskMetaCall::invoke( QObject* object,
|
||||
const Invokable& invokable, void* args[],
|
||||
const Invokable& invokable, int argc, const int argTypes[], void* argv[],
|
||||
Qt::ConnectionType connectionType )
|
||||
{
|
||||
//connectionType &= ~Qt::UniqueConnection;
|
||||
@ -117,14 +166,36 @@ void QskMetaCall::invoke( QObject* object,
|
||||
|
||||
if ( connectionType == Qt::DirectConnection )
|
||||
{
|
||||
invokablePtr->call( object, args );
|
||||
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 QMetaCallEvent(
|
||||
invokablePtr, nullptr, 0, 0, nullptr, args, nullptr );
|
||||
auto event = new FunctionCallEvent(
|
||||
invokablePtr, argc, types, arguments, nullptr );
|
||||
|
||||
QCoreApplication::postEvent( object, event );
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ namespace QskMetaCall
|
||||
Qt::ConnectionType = Qt::AutoConnection );
|
||||
|
||||
QSK_EXPORT void invoke( QObject*,
|
||||
const Invokable&, void* args[],
|
||||
const Invokable&, int argc, const int argTypes[], void* args[],
|
||||
Qt::ConnectionType = Qt::AutoConnection );
|
||||
}
|
||||
|
||||
|
@ -4,82 +4,11 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskMetaCallback.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
#include <QSemaphore>
|
||||
|
||||
#include <private/qobject_p.h>
|
||||
|
||||
static void qskInvoke( 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 ) ) );
|
||||
|
||||
types[0] = QMetaType::UnknownType; // return type
|
||||
|
||||
for ( int i = 1; i < paramCount; i++ )
|
||||
{
|
||||
types[i] = method.parameterType( i );
|
||||
Q_ASSERT( args[i] != nullptr );
|
||||
}
|
||||
|
||||
Q_ASSERT( args[paramCount] == nullptr );
|
||||
|
||||
if ( connectionType == Qt::QueuedConnection )
|
||||
{
|
||||
QMetaCallEvent* event = new QMetaCallEvent(
|
||||
methodOffset, methodIndex, metaObject->d.static_metacall,
|
||||
nullptr, -1, paramCount + 1, types, args );
|
||||
|
||||
QCoreApplication::postEvent(object, event );
|
||||
}
|
||||
else
|
||||
{
|
||||
QSemaphore semaphore;
|
||||
|
||||
// what about argc + types ???
|
||||
auto event = new QMetaCallEvent(
|
||||
methodOffset, methodIndex, metaObject->d.static_metacall,
|
||||
nullptr, -1, 0, 0, args, &semaphore );
|
||||
|
||||
QCoreApplication::postEvent( object, event );
|
||||
|
||||
semaphore.acquire();
|
||||
}
|
||||
}
|
||||
}
|
||||
#include <QVector>
|
||||
|
||||
QskMetaCallback::QskMetaCallback( const QObject* object,
|
||||
const QMetaMethod& method, Qt::ConnectionType connectionType ):
|
||||
const QMetaMethod& method, Qt::ConnectionType connectionType ):
|
||||
m_object( const_cast< QObject* >( object ) ),
|
||||
m_method( method ),
|
||||
m_type( MetaMethod ),
|
||||
@ -156,6 +85,11 @@ QskMetaCallback& QskMetaCallback::operator=( const QskMetaCallback& other )
|
||||
return *this;
|
||||
}
|
||||
|
||||
void QskMetaCallback::setConnectionType( Qt::ConnectionType connectionType )
|
||||
{
|
||||
m_connectionType = connectionType;
|
||||
}
|
||||
|
||||
void QskMetaCallback::reset()
|
||||
{
|
||||
switch( m_type )
|
||||
@ -218,7 +152,7 @@ void QskMetaCallback::invoke( void* args[] )
|
||||
case MetaMethod:
|
||||
{
|
||||
if ( object )
|
||||
qskInvoke( object, m_method, args, connectionType() );
|
||||
QskMetaCall::invoke( object, m_method, args, connectionType() );
|
||||
break;
|
||||
}
|
||||
case MetaFunction:
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QMetaMethod>
|
||||
#include <QVector>
|
||||
|
||||
class QskMetaCallback
|
||||
{
|
||||
@ -28,8 +29,13 @@ public:
|
||||
};
|
||||
|
||||
QskMetaCallback();
|
||||
QskMetaCallback( const QObject*, const QskMetaFunction&, Qt::ConnectionType );
|
||||
QskMetaCallback( const QObject*, const QMetaMethod&, Qt::ConnectionType );
|
||||
|
||||
QskMetaCallback( const QObject*, const QskMetaFunction&,
|
||||
Qt::ConnectionType = Qt::AutoConnection );
|
||||
|
||||
QskMetaCallback( const QObject*, const QMetaMethod&,
|
||||
Qt::ConnectionType = Qt::AutoConnection );
|
||||
|
||||
QskMetaCallback( const QskMetaCallback& );
|
||||
|
||||
~QskMetaCallback();
|
||||
@ -40,6 +46,8 @@ public:
|
||||
bool isValid() const;
|
||||
|
||||
const QObject* object() const { return m_object; }
|
||||
|
||||
void setConnectionType( Qt::ConnectionType );
|
||||
Qt::ConnectionType connectionType() const;
|
||||
|
||||
QVector< int > parameterTypes() const;
|
||||
@ -51,11 +59,17 @@ private:
|
||||
|
||||
QPointer< const QObject > m_object;
|
||||
|
||||
#if 1
|
||||
/*
|
||||
This union does not work - call of constructors
|
||||
are missing
|
||||
*/
|
||||
union
|
||||
{
|
||||
QskMetaFunction m_function;
|
||||
QMetaMethod m_method;
|
||||
};
|
||||
#endif
|
||||
|
||||
int m_type : 3;
|
||||
ushort m_connectionType : 3;
|
||||
|
@ -68,11 +68,38 @@ QskMetaFunction& QskMetaFunction::operator=( const QskMetaFunction& other )
|
||||
return *this;
|
||||
}
|
||||
|
||||
void QskMetaFunction::init( QskMetaCall::Invokable* invokable,
|
||||
const int* parameterTypes )
|
||||
{
|
||||
m_invokable = invokable;
|
||||
#if 0
|
||||
if ( m_invokable )
|
||||
m_invokable->ref();
|
||||
#endif
|
||||
|
||||
m_parameterTypes = parameterTypes;
|
||||
}
|
||||
|
||||
const int* QskMetaFunction::parameterTypes() const
|
||||
{
|
||||
return m_parameterTypes;
|
||||
}
|
||||
|
||||
size_t QskMetaFunction::parameterCount() const
|
||||
{
|
||||
if ( m_parameterTypes )
|
||||
{
|
||||
for ( int i = 1; ; i++ )
|
||||
{
|
||||
if ( m_parameterTypes[ i ] == QMetaType::UnknownType )
|
||||
return i + 1; // including the return type
|
||||
}
|
||||
}
|
||||
|
||||
return 1; // we always have a return type
|
||||
}
|
||||
|
||||
|
||||
QskMetaFunction::Type QskMetaFunction::functionType() const
|
||||
{
|
||||
if ( m_invokable == nullptr )
|
||||
@ -82,8 +109,11 @@ QskMetaFunction::Type QskMetaFunction::functionType() const
|
||||
}
|
||||
|
||||
void QskMetaFunction::invoke(
|
||||
QObject* object, void* args[], Qt::ConnectionType connectionType )
|
||||
QObject* object, void* argv[], Qt::ConnectionType connectionType )
|
||||
{
|
||||
if ( m_invokable )
|
||||
QskMetaCall::invoke( object, *m_invokable, args, connectionType );
|
||||
{
|
||||
QskMetaCall::invoke( object, *m_invokable,
|
||||
parameterCount(), parameterTypes(), argv, connectionType );
|
||||
}
|
||||
}
|
||||
|
@ -53,12 +53,17 @@ public:
|
||||
|
||||
const int* parameterTypes() const;
|
||||
|
||||
// including the return type !
|
||||
size_t parameterCount() const;
|
||||
|
||||
void invoke( QObject*, void* args[],
|
||||
Qt::ConnectionType = Qt::AutoConnection );
|
||||
|
||||
Type functionType() const;
|
||||
|
||||
private:
|
||||
void init( QskMetaCall::Invokable*, const int* );
|
||||
|
||||
QskMetaCall::Invokable* m_invokable;
|
||||
const int* m_parameterTypes;
|
||||
};
|
||||
@ -75,8 +80,8 @@ inline QskMetaFunction::QskMetaFunction( T function )
|
||||
const int Argc = Traits::ArgumentCount;
|
||||
using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
|
||||
|
||||
m_invokable = new MemberFunctionInvokable< T, Args, void >( function );
|
||||
m_parameterTypes = ConnectionTypes< typename Traits::Arguments >::types();
|
||||
init( new MemberFunctionInvokable< T, Args, void >( function ),
|
||||
ConnectionTypes< typename Traits::Arguments >::types() );
|
||||
}
|
||||
|
||||
template< typename T, QskMetaCall::IsFunction< T >* >
|
||||
@ -90,8 +95,8 @@ inline QskMetaFunction::QskMetaFunction( T function )
|
||||
const int Argc = Traits::ArgumentCount;
|
||||
using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
|
||||
|
||||
m_invokable = new FunctionInvokable< T, Args, void >( function );
|
||||
m_parameterTypes = ConnectionTypes< typename Traits::Arguments >::types();
|
||||
init( new FunctionInvokable< T, Args, void >( function ),
|
||||
ConnectionTypes< typename Traits::Arguments >::types() );
|
||||
}
|
||||
|
||||
template< typename T, QskMetaCall::IsFunctor< T >* >
|
||||
@ -104,8 +109,8 @@ inline QskMetaFunction::QskMetaFunction( T functor )
|
||||
const int Argc = Traits::ArgumentCount;
|
||||
using Args = typename List_Left< typename Traits::Arguments, Argc >::Value;
|
||||
|
||||
m_invokable = new QskMetaCall::FunctorInvokable< T, Argc, Args, void > ( functor );
|
||||
m_parameterTypes = ConnectionTypes< typename Traits::Arguments >::types();
|
||||
init( new QskMetaCall::FunctorInvokable< T, Argc, Args, void > ( functor ),
|
||||
ConnectionTypes< typename Traits::Arguments >::types() );
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE( QskMetaFunction )
|
||||
|
Loading…
x
Reference in New Issue
Block a user