Commit 5ea0c29c authored by Jan Möbius's avatar Jan Möbius

More on OpenFlipper Threads

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@7308 383ad7c9-94d9-4d36-a494-682f7c89f535
parent d033dc09
...@@ -65,7 +65,8 @@ ...@@ -65,7 +65,8 @@
* connect(thread,SIGNAL( finished(QString)), this,SIGNAL(finishJob(QString))); // connect your threads finish info to the global one ( you can do the same for a local one ) \n * connect(thread,SIGNAL( finished(QString)), this,SIGNAL(finishJob(QString))); // connect your threads finish info to the global one ( you can do the same for a local one ) \n
* connect(thread,SIGNAL( function()), this,SLOT(testFunctionThread()),Qt::DirectConnection); // You can directly give a slot of your app that gets called \n * connect(thread,SIGNAL( function()), this,SLOT(testFunctionThread()),Qt::DirectConnection); // You can directly give a slot of your app that gets called \n
* emit startJob( name() + "1", "Description" , 0 , 100 , false); // Tell the core about your thread * emit startJob( name() + "1", "Description" , 0 , 100 , false); // Tell the core about your thread
* thread->start(); // start execution * thread->start(); // start thread
* thread->startProcessing(); // start processing
*/ */
class ProcessInterface { class ProcessInterface {
......
...@@ -33,9 +33,12 @@ ...@@ -33,9 +33,12 @@
#include "OpenFlipperThread.hh" #include "OpenFlipperThread.hh"
#include <iostream> #include <iostream>
OpenFlipperThread::OpenFlipperThread( QString _jobId ) : OpenFlipperThread::OpenFlipperThread( QString _jobId ) :
job_(0),
jobId_(_jobId) jobId_(_jobId)
{ {
startup_.lock();
} }
...@@ -45,18 +48,29 @@ OpenFlipperThread::~OpenFlipperThread() { ...@@ -45,18 +48,29 @@ OpenFlipperThread::~OpenFlipperThread() {
void OpenFlipperThread::run() void OpenFlipperThread::run()
{ {
std::cerr << "Start Function" << std::endl; if ( job_ == 0 ) {
// Create a job wrapper to run a slot from within this thread
job_ = new OpenFlipperJob();
// This starts the function in our local thread if DirectConnection is used! // Connect the slot which should run in this thread. This has to be a DirectConnection !
emit function(); // Otherwisse the slot will run inside its owner context which will be the main loop!!
connect(job_, SIGNAL(process()),this,SIGNAL(function() ),Qt::DirectConnection);
// Connect the jobs finished function
connect(job_, SIGNAL(finished()),this,SLOT(slotJobFinished() ) );
// connect the function to start the job
connect(this,SIGNAL(startProcessingInternal()),job_,SLOT(startJobProcessing()),Qt::QueuedConnection);
}
// Emit a message that our job is finished std::cerr << "Start Loop" << std::endl;
emit finished(jobId_);
startup_.unlock();
std::cerr << "Done " << std::endl; // Start event queue
exec();
// start event loop of thread std::cerr << "End Loop" << std::endl;
// exec();
} }
void OpenFlipperThread::cancel() { void OpenFlipperThread::cancel() {
...@@ -67,3 +81,34 @@ void OpenFlipperThread::slotCancel( QString _jobId) { ...@@ -67,3 +81,34 @@ void OpenFlipperThread::slotCancel( QString _jobId) {
if ( _jobId == jobId_ ) if ( _jobId == jobId_ )
cancel(); cancel();
} }
void OpenFlipperThread::slotJobFinished( ) {
emit finished( jobId_ );
}
void OpenFlipperThread::startProcessing() {
std::cerr << "Thread emit startProcessing" << std::endl;
// Wait for thread to come up with event loop
startup_.lock();
// Tell internal wrapper to start with the processing
emit startProcessingInternal();
startup_.unlock();
std::cerr << "Thread emit startProcessing done" << std::endl;
}
void OpenFlipperJob::startJobProcessing() {
std::cerr << "job emit process" << std::endl;
// Actually start the process ( This function will block as it uses a direct connection )
// But it only blocks the current thread.
emit process();
// Tell thread that the job is done.
emit finished();
std::cerr << "job emit process done" << std::endl;
}
...@@ -36,10 +36,15 @@ ...@@ -36,10 +36,15 @@
#define OPENFLIPPERTHREAD_HH #define OPENFLIPPERTHREAD_HH
#include <QThread> #include <QThread>
#include <QMutex>
#include <QProgressDialog> #include <QProgressDialog>
#include <OpenFlipper/common/GlobalDefines.hh> #include <OpenFlipper/common/GlobalDefines.hh>
class OpenFlipperJob;
class DLLEXPORT OpenFlipperThread : public QThread class DLLEXPORT OpenFlipperThread : public QThread
{ {
Q_OBJECT Q_OBJECT
...@@ -48,19 +53,26 @@ class DLLEXPORT OpenFlipperThread : public QThread ...@@ -48,19 +53,26 @@ class DLLEXPORT OpenFlipperThread : public QThread
OpenFlipperThread( QString _jobId ); OpenFlipperThread( QString _jobId );
~OpenFlipperThread(); ~OpenFlipperThread();
//===========================================================================
/** @name Advanced job processing
* @{ */
//===========================================================================
public:
/** \brief Main processing /** \brief Main processing
* *
* Connect a function to the function() signal ( DirectConnection!!! ) * Connect a function to the function() signal ( DirectConnection!!! )
* Or reimplement this function * Or reimplement this function
*/ */
virtual void run(); virtual void run();
/** Reimplement this if you have to take care about how your process is canceled
*/
virtual void cancel();
private: /** \brief Cancel the job
QString jobId_; *
* Reimplement this function to correctly terminate your job.
* If your job is able to terminate correctly then you can reimplement this function
* and stop your process.
*/
virtual void cancel();
public slots: public slots:
/** Call this slot with the correct job id to abort processing /** Call this slot with the correct job id to abort processing
...@@ -70,22 +82,143 @@ class DLLEXPORT OpenFlipperThread : public QThread ...@@ -70,22 +82,143 @@ class DLLEXPORT OpenFlipperThread : public QThread
void slotCancel( QString _jobId); void slotCancel( QString _jobId);
signals: signals:
/// Emit this signal to tell the core about your job status /** \brief Tell core about job state
*
* Emit this signal to tell the core about your job status. You have to create a new run function for
* this. In simple mode, this signal is not emitted at all!
*/
void state( QString _jobId, int _state ); void state( QString _jobId, int _state );
/// This signal is emitted if your job has finished /** @} */
void finished( QString _jobId );
/** The thread directly calls this function. You do not have to derive from OpenFlipperThread ( although this is
* necessary to update the core about your progress via state(). //===========================================================================
* You can also connect one of your slots using \n /** @name Simple job processing
* @{ */
//===========================================================================
signals:
/** \brief job function
*
* If you do not specialize the OpenFlipperThread, The function connected to this
* signal will be used as the processing function for your thread. When you call
* OpenFlipper::startProcessing(); \n
*
* If you want to provide more feedback (% of runtime) or cancel the job,
* you have to derive from OpenFlipperThread and emit the right signals.
*
* You have connect one of your slot using \n
* connect( OpenFlipperThread ,SIGNAL(function()),YourPlugin,SLOT(YourSlot(),Qt::DirectConnection) );\n * connect( OpenFlipperThread ,SIGNAL(function()),YourPlugin,SLOT(YourSlot(),Qt::DirectConnection) );\n
* The default implementation will call your slot inside the given thread and the core will still respond. * The default implementation will call your slot inside the given thread and the core will still respond.
* However you should only use this function if you Dont know how long your job takes. \n * However you should only use this function if you Dont know how long your job takes. Or when
* Otherwise you should reimplement the run() function of OpenFlipperThread. * you just want to keep the core responding.\n
* Otherwise you should reimplement the run(), and cancel() function of OpenFlipperThread and emit the state signal.
*/ */
void function(); void function();
/** \brief job done
*
* This signal is emitted if your job has finished and should be used to tell the core that your job has finished.
*
*/
void finished( QString _jobId );
public slots:
/** \brief start processing
*
* This function will start the actuall processing of a job.
*/
void startProcessing();
/** @} */
private slots:
/** \brief job has finished
*
* Called by the job wrapper, when the job is done.
*/
void slotJobFinished();
signals:
/** \brief start processing of a function
*
* (INTERNAL!) \n
* This signal is used to start the process execution through the wrapper
*/
void startProcessingInternal();
private:
/** \brief Internal job wrapper
*
* (INTERNAL!) \n
* This wrapper is used to start slots inside the event queue of the current thread.
* All slots defined in the QThread object live in the callers thread(The main thread).
* All slots inside the wrapper live in the thread created by QThread. and therefore
* do not lock the main event loop
*/
OpenFlipperJob* job_;
/** \brief Id of the current job
*
* This holds the id of the current job. Most functions only react if the correct id is passed
* to the function.
*/
QString jobId_;
QMutex startup_;
};
// ================================================================================
// Job wrapper
// ================================================================================
/** \brief Internal Job execution object
*
* This class is used to start a process within a thread. The thread object itself
* lives in the event queue of the object that crreated the thread. So every signal
* or slot within the qthread object will be dispatched in the core event loop and
* therefore lock the gui.
* Objects created in the qthread will run in the threads event queue as well as their
* signals and slots. So qthread uses this object to actually run arbitrary threads
* inside the threads event queue.
*/
class DLLEXPORT OpenFlipperJob : public QObject
{
Q_OBJECT
public:
OpenFlipperJob() {}
~OpenFlipperJob() {}
signals:
/** \brief connection to actual processing function
*
* This signal has to be connected via a Qt::DirectConnection to an
* arbitrary slot. This slot will be executed in the local event queue.
* If this object is created in a QThread, than the slot will be run
* inside this thread.
*/
void process();
/** \brief Job done
*
* This signal is emitted, when the job has finished
*/
void finished();
public slots:
/** \brief slot to start processing
*
* If this slot is called, the slot connected to process() will be executed
* in the current thread.
*/
void startJobProcessing();
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment