PARP Research Group University of Murcia, Spain


src/qvcore/qvworker.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024  
00025 #include <iostream>
00026 
00027 #include <QDebug>
00028 #include <QMutex>
00029 #include <QWaitCondition>
00030 #include <QApplication>
00031 
00032 #include <QVWorker>
00033 
00034 QVWorker::QVWorker(const QString name):QVPropertyContainer(name), numIterations(0), status(Running), triggerList(), minms(0)
00035         {
00036         qDebug() << "QVWorker::QVWorker(" << name << ")";
00037         Q_ASSERT_X(qvApp != NULL, "QVWorker::QVWorker()", "QVApplication doesn't exists");
00038         if (qvApp == NULL)
00039                 {
00040                 QString str = "QVWorker::QVWorker(): the QVWorker cannot be created before the QVApplication instance. Aborting now.";
00041                 std::cerr << qPrintable(str) << std::endl;
00042                 exit(1);
00043                 }
00044 
00045         addProperty<int>("max worker iterations", inputFlag | guiInvisible | internalProp, -1, "Stablishes maximal number of iterations to execute worker");
00046         maxIterations = getPropertyValue<int>("max worker iterations");
00047 
00048         addProperty<bool>("stats enabled", inputFlag | guiInvisible | internalProp, TRUE, "Stablishes if the worker's cpu stats will be enabled");
00049         statsEnabled = getPropertyValue<bool>("stats enabled");
00050         if (statsEnabled) cpuStatControler = new QVStatControler();
00051         if (statsEnabled)       addProperty<QVStat>("cpu stats", outputFlag, cpuStatControler->value(), "CPU stats's Statistics");
00052         else                            addProperty<QVStat>("cpu stats", outputFlag, QVStat(), "CPU stats's Statistics");
00053 
00054 
00055 //      informer->setParent(this); // set the informer's parent = this, in order to it will be moved to the worker's thread when the qvApp do worker->moveToThread(worker)
00056         qDebug() << "QVWorker::QVWorker(" << name << ") <- return";
00057         };
00058 
00059 QVWorker::QVWorker(const QVWorker &other):QThread(), QVPropertyContainer(other), statsEnabled(other.statsEnabled), numIterations(other.numIterations),
00060         maxIterations(other.maxIterations), status(other.status), triggerList(other.triggerList), iterationTime(other.iterationTime), curms(other.curms),
00061         minms(other.minms)
00062         {
00063         if (statsEnabled) cpuStatControler = new QVStatControler();
00064         }
00065 
00066 QVWorker::~QVWorker()
00067         {
00068         if (statsEnabled)
00069                 delete cpuStatControler;
00070 
00071 //      if (informer != 0) delete informer;
00072         }
00073 /*
00074 void QVWorker::unlink()
00075         {
00076         if(status == Finished)
00077                 QVPropertyContainer::unlink();
00078         else
00079                 std::cerr << "WARNING: A worker only can be unlinked if the worker's status is Finished." << std::endl;
00080         }
00081 */
00082 void QVWorker::run()
00083         {
00084         qDebug() << "QVWorker::run()";
00085 
00086         while(status != Finished)
00087                 {
00088                 qDebug() << "Processing events in worker " << qPrintable(getName());
00089 
00090                 // First, we check if there are any pending signals, and if so, we
00091                 // execute their associated slots:
00092                 qApp->processEvents();
00093 
00094                 qDebug() << "QVWorker::iterate(): iteration" << numIterations;
00095         
00096                 // Avoids "apparent hanging" (greedy ocupation of CPU by extremely fast
00097                 // workers, such as paused ones). It is just 0.5 milliseconds, so
00098                 // it should not be appreciable in any practical situation.
00099                 usleep(500);
00100 
00101                 switch (status)
00102                         {
00103                         case RunningOneStep:
00104                                 qDebug() << "QVWorker::iterate(): RunningOneStep";
00105                                 status = Paused;
00106 
00107                         case Running:
00108                                 iterationTime.start();
00109                                 foreach(QList<QVPropertyContainer *> level, slavesByLevel) {
00110                                         foreach(QVPropertyContainer * slave, level) {
00111                                                 QVWorker* worker;
00112                                                 if((worker = dynamic_cast<QVWorker*>(slave)) != NULL) {
00113                                                         worker->workerIterate();
00114                                                 }
00115                                         }
00116                                 }
00117                                 curms = iterationTime.elapsed();
00118                                 if(minms > curms)
00119                                         usleep(1000*(minms-curms));
00120                                 /*if(numIterations!=1) // First iteration time is too noisy:
00121                                         acumms = (acumms*(numIterations-2) + curms) / (numIterations-1);
00122                                 std::cout << "-----> curms=" << curms << " acumms=" << acumms << "\n";*/
00123                                 break;
00124 
00125                         case Stoped:
00126                                 // A stopped worker should never block anybody, but keeps linked to
00127                                 // other workers (otherwise, it would simply be deleted). So, it must
00128                                 // read its inputs an write its outputs always, even being stopped.
00129                                 readInputProperties();
00130                                 writeOutputProperties();
00131                                 usleep(100); // This avoids spurious CPU consuming when stopped.
00132                                 break;
00133 
00134         
00135                         case Paused:
00136                                 qDebug() << "QVWorker::iterate(): Paused";
00137                                 usleep(100); // This avoids spurious CPU consuming when paused.
00138                                 break;
00139 
00140                         case Finished:
00141                                 qDebug() << "QVWorker::iterate(): Finished";
00142                                 break;
00143                         }
00144 
00145                 if (maxIterations != -1 && numIterations >= maxIterations)
00146                         finish();
00147 
00148                 qDebug() << "QVWorker::iterate() <- return";
00149                 }
00150 
00151         unlink();
00152         qDebug() << "QVWorker::run() <- return";
00153         }
00154 
00155 void QVWorker::workerIterate()
00156         {
00157         if (statsEnabled) cpuStatControler->step();
00158         emit startIteration(); // if it is connect to a camera, it will be wait the camera grab()
00159         readInputProperties();
00160         timeFlag("System");
00161         if (status != Stoped) iterate();
00162         if (statsEnabled) setPropertyValue<QVStat>("cpu stats", cpuStatControler->value());
00163         writeOutputProperties();
00164         numIterations++;
00165         emit endIteration(getId(), getIteration());
00166         }
00167 



QVision framework. PARP research group, copyright 2007, 2008.