Needing a QEventLoop for a kioslave

Friedrich W. H. Kossebau kossebau at kde.org
Tue Feb 10 23:32:16 GMT 2009


Le mardi, 10. février 2009, à 22:22, Friedrich W. H. Kossebau a écrit:
> Le lundi, 9. février 2009, à 19:01, Thiago Macieira a écrit:
> > Em Segunda-feira 09 Fevereiro 2009, às 17:15:36, Friedrich W. H. Kossebau
> >
> > escreveu:
> > > What shall I do if the 3-party code I use as backend to generate/pull
> > > the data for the ioslave depends on a running event loop? E.g. if using
> > > a QTimer IIUC? Could there be an option for the dispatchLoop() to also
> > > care for QEvents? Or can I use a thread? Is there any example code I
> > > could look at?
> >
> > Use a thread.
>
> What to do then with static QObjects created by K_GLOBAL_STATIC inside the
> 3-party code? It is said all QObject created in the thread have to be
> deleted before the thread ends. So if I wrap the execution of the non-gui
> (KDE) library code in a thread not the main QCoreApplication::exec() one,
> can/will K_GLOBAL_STATIC bind them to the thread somehow?

I have got my kioslave now running (see below), but still wonder what the 
answer here is, does the kioslave on exit pull down all memory constructs 
cleanly, or how could one achieve this?

> I for now tried a q'n'd approach I found for the JabberDisco in Kopete. But
> it does not work for me, is this non-ported KDE 3 code or is there a flaw?
>
> --- 8< ---
> bool breakEventLoop = false;
>
> class EventLoopThread : public QThread
> {
> public:
> 	void run ();
> };
>
> void EventLoopThread::run ()
> {
> 	while ( true )
> 	{
> 		qApp->processEvents ();

Guess this just fails, because QCoreApplication::exec() was never called, so 
there is no main QEventLoop?

> 		msleep ( 100 );
>
> 		if ( breakEventLoop )
> 			break;
> 	}
> }
>
> void JabberDiscoProtocol::dispatchLoop ()
> {
> 	EventLoopThread eventLoopThread;
>
> 	eventLoopThread.start ();
> 	SlaveBase::dispatchLoop ();
> 	breakEventLoop = true;
> 	eventLoopThread.wait ();
> }
> --- 8< ---

I now have the following solution: I have the lib code execute in the thread, 
and if I need access to some data from the lib I just pause it, access the 
data, and then unpause it again, so it can update the internal data 
structures on external changes.

So the slave contains this code:
    mNetworkThread->pause();
    Network* network = mNetworkThread->network();
    // extract all data needed from network
    mNetworkThread->unpause();

And the thread class looks this way:
--- 8< ---
class NetworkThread : public QThread
{
  public:
    NetworkThread();

  public:
    Network* network() const;
    void pause();
    void unpause();

  protected: // QThread API
    virtual void run();

  private:
    QMutex mMutex;
    Network* mNetwork;
};

NetworkThread::NetworkThread()
  : QThread()
  , mNetwork( 0 )
{}

Network* NetworkThread::network() const { return mNetwork; }

void NetworkThread::pause()
{
    mMutex.lock();
    exit();
}

void NetworkThread::unpause()
{
    mMutex.unlock();
}

void NetworkThread::run()
{
    mNetwork = Network::network();
    forever
    {
        exec();
        mMutex.lock();
        mMutex.unlock();
    }
}
--- 8< ---

Smart solution? Or is there a better way?

The code is now to be found, at 
http://websvn.kde.org/trunk/playground/network/networkkio/

Cheers
Friedrich
-- 
Okteta - KDE 4 Hex Editor - http://utils.kde.org/projects/okteta




More information about the kde-core-devel mailing list