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 @@
* 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
* 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 {
......
......@@ -33,9 +33,12 @@
#include "OpenFlipperThread.hh"
#include <iostream>
OpenFlipperThread::OpenFlipperThread( QString _jobId ) :
job_(0),
jobId_(_jobId)
{
startup_.lock();
}
......@@ -45,18 +48,29 @@ OpenFlipperThread::~OpenFlipperThread() {
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!
emit function();
// Connect the slot which should run in this thread. This has to be a DirectConnection !
// 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
emit finished(jobId_);
std::cerr << "Start Loop" << std::endl;
startup_.unlock();
std::cerr << "Done " << std::endl;
// Start event queue
exec();
// start event loop of thread
// exec();
std::cerr << "End Loop" << std::endl;
}
void OpenFlipperThread::cancel() {
......@@ -67,3 +81,34 @@ void OpenFlipperThread::slotCancel( QString _jobId) {
if ( _jobId == jobId_ )
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 @@
#define OPENFLIPPERTHREAD_HH
#include <QThread>
#include <QMutex>
#include <QProgressDialog>
#include <OpenFlipper/common/GlobalDefines.hh>
class OpenFlipperJob;
class DLLEXPORT OpenFlipperThread : public QThread
{
Q_OBJECT
......@@ -48,19 +53,26 @@ class DLLEXPORT OpenFlipperThread : public QThread
OpenFlipperThread( QString _jobId );
~OpenFlipperThread();
//===========================================================================
/** @name Advanced job processing
* @{ */
//===========================================================================
public:
/** \brief Main processing
*
* Connect a function to the function() signal ( DirectConnection!!! )
* Or reimplement this function
*/
virtual void run();
/** Reimplement this if you have to take care about how your process is canceled
*/
virtual void cancel();
private:
QString jobId_;
/** \brief Cancel the job
*
* 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:
/** Call this slot with the correct job id to abort processing
......@@ -70,22 +82,143 @@ class DLLEXPORT OpenFlipperThread : public QThread
void slotCancel( QString _jobId);
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 );
/// 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
* 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
* Otherwise you should reimplement the run() function of OpenFlipperThread.
* However you should only use this function if you Dont know how long your job takes. Or when
* 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();
/** \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