I missed the Ice:Dispatcher API. I don't think it was mentioned in the release notes...). I will need to figure out the implications...
The nice thing about using Ice:Dispatcher is that it lets you route all incoming calls into the Qt thread as well.
Here's my implementation of a Qt version of Dispatcher.
qtdispatcher.h
Code:
#ifndef QTDISPATCHER_H
#define QTDISPATCHER_H
#include <QObject>
#include <Ice/Dispatcher.h>
class QtDispatcher : public QObject,
public Ice::Dispatcher
{
Q_OBJECT
public:
QtDispatcher( bool debug=false );
// from Ice::Dispatcher
// This function is called from inside the Ice thread pool.
// If an instance of QApplication already exists, post a Qt event to itself.
// The event contains dispatcher call and connection information.
// It will be recieved and processed by customEvent().
virtual void dispatch( const Ice::DispatcherCallPtr& d, const Ice::ConnectionPtr& c );
private:
// from QObject
// This event is called from inside the Qt main event loop (the Qt "GUI thread")
// Processes events sent by dispatch().
virtual void customEvent( QEvent* e );
bool debug_;
};
#endif
qtdispatcher.cpp
Code:
#include "qtdispatcher.h"
#include <QApplication>
#include <Ice/Connection.h>
#include <iostream>
using namespace std;
namespace {
const int CUSTOM_EVENT_TYPE = QEvent::User+4021;
// This event is internal to the library, not used by the end user.
class DispatchEvent : public QEvent
{
public:
DispatchEvent( const Ice::DispatcherCallPtr& d, const Ice::ConnectionPtr& c ) :
QEvent( QEvent::Type(CUSTOM_EVENT_TYPE) ),
dispatcherCall(d),
connection(c)
{};
Ice::DispatcherCallPtr dispatcherCall;
Ice::ConnectionPtr connection;
};
}
////////////////////////////
QtDispatcher::QtDispatcher( bool debug ) :
debug_(debug)
{
}
void
QtDispatcher::dispatch( const Ice::DispatcherCallPtr& d, const Ice::ConnectionPtr& c )
{
if ( debug_ ) {
if ( c->getInfo()->incoming )
cout<<"QtDispatcher::"<<__func__<<"(): incoming call"<<endl;
else
cout<<"QtDispatcher::"<<__func__<<"(): AMI call"<<endl;
}
if ( qApp ) {
if ( debug_ )
cout<<"QtDispatcher::dispatch(): dispatching event with qApp->postEvent()"<<endl;
qApp->postEvent( this, (QEvent*)new DispatchEvent( d, c ) );
}
else {
if ( debug_ )
cout<<"QtDispatcher::dispatch(): executing remote call directly with d->run()"<<endl;
d->run(); // Does not throw, blocks until op completes.
}
}
void
QtDispatcher::customEvent( QEvent* event )
{
if ( debug_ )
cout<<"QtDispatcher::"<<__func__<<"()"<<endl;
assert( event->type() == CUSTOM_EVENT_TYPE );
DispatchEvent* e = dynamic_cast<DispatchEvent*>(event);
assert( e );
try {
e->dispatcherCall->run(); // Does not throw, blocks until op completes.
}
catch ( const Ice::Exception& e ) {
cout<<"QtDispatcher::customEvent(): caught ex: "<<e<<endl;
}
}