ThreadWeaver
JobCollection.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "JobCollection.h"
00030 #include "JobCollection_p.h"
00031
00032 #include "WeaverInterface.h"
00033 #include "DebuggingAids.h"
00034
00035 #include <QtCore/QList>
00036 #include <QtCore/QObject>
00037 #include <QtCore/QPointer>
00038
00039 #include "DependencyPolicy.h"
00040
00041 using namespace ThreadWeaver;
00042
00043 JobCollectionJobRunner::JobCollectionJobRunner ( JobCollection* collection, Job* payload, QObject* parent )
00044 : Job( parent )
00045 , m_payload( payload )
00046 , m_collection( collection )
00047 {
00048 Q_ASSERT ( payload );
00049
00050 if ( ! m_payload->objectName().isEmpty() )
00051 {
00052 setObjectName( tr( "JobRunner executing " ) + m_payload->objectName() );
00053 } else {
00054 setObjectName( tr( "JobRunner (unnamed payload)" ) );
00055 }
00056 }
00057
00058 bool JobCollectionJobRunner::canBeExecuted()
00059 {
00060 return m_payload->canBeExecuted();
00061 }
00062
00063 Job* JobCollectionJobRunner::payload ()
00064 {
00065 return m_payload;
00066 }
00067
00068 void JobCollectionJobRunner::aboutToBeQueued ( WeaverInterface *weaver )
00069 {
00070 m_payload->aboutToBeQueued( weaver );
00071 }
00072
00073 void JobCollectionJobRunner::aboutToBeDequeued ( WeaverInterface *weaver )
00074 {
00075 m_payload->aboutToBeDequeued( weaver );
00076 }
00077
00078 void JobCollectionJobRunner::execute ( Thread *t )
00079 {
00080 if ( m_payload )
00081 {
00082 m_payload->execute ( t );
00083 m_collection->internalJobDone ( m_payload);
00084 } else {
00085 debug ( 1, "JobCollection: job in collection has been deleted." );
00086 }
00087 Job::execute ( t );
00088 }
00089
00090 int JobCollectionJobRunner::priority () const
00091 {
00092 return m_payload->priority();
00093 }
00094
00095 void JobCollectionJobRunner::run ()
00096 {
00097 }
00098
00099 class JobList : public QList <JobCollectionJobRunner*> {};
00100
00101 class JobCollection::Private
00102 {
00103 public:
00104
00105 Private()
00106 : elements ( new JobList() )
00107 , weaver ( 0 )
00108 , jobCounter (0)
00109 {}
00110
00111 ~Private()
00112 {
00113 delete elements;
00114 }
00115
00116
00117 JobList* elements;
00118
00119
00120 WeaverInterface *weaver;
00121
00122
00123
00124
00125
00126 int jobCounter;
00127
00128 QMutex mutex;
00129 };
00130
00131 JobCollection::JobCollection ( QObject *parent )
00132 : Job ( parent )
00133 , d (new Private)
00134 {
00135 }
00136
00137 JobCollection::~JobCollection()
00138 {
00139 if ( d->weaver != 0 )
00140 dequeueElements();
00141
00142 delete d;
00143 }
00144
00145 void JobCollection::addJob ( Job *job )
00146 {
00147 REQUIRE( d->weaver == 0 );
00148 REQUIRE( job != 0);
00149 d->elements->append ( new JobCollectionJobRunner( this, job, this ) );
00150 }
00151
00152 void JobCollection::stop( Job *job )
00153 {
00154
00155 Q_UNUSED( job );
00156 if ( d->weaver != 0 )
00157 {
00158 debug( 4, "JobCollection::stop: dequeueing %p.\n", this);
00159 d->weaver->dequeue( this );
00160 }
00161
00162 }
00163
00164 void JobCollection::aboutToBeQueued ( WeaverInterface *weaver )
00165 {
00166 REQUIRE ( d->weaver == 0 );
00167
00168 d->weaver = weaver;
00169
00170 if ( d->elements->size() > 0 )
00171 {
00172 d->elements->at( 0 )->aboutToBeQueued( weaver );
00173 }
00174
00175 ENSURE(d->weaver != 0);
00176 }
00177
00178 void JobCollection::aboutToBeDequeued( WeaverInterface* weaver )
00179 {
00180
00181
00182
00183 if ( d->weaver )
00184 {
00185 dequeueElements();
00186
00187 d->elements->at( 0 )->aboutToBeDequeued( weaver );
00188 }
00189
00190 d->weaver = 0;
00191 ENSURE ( d->weaver == 0 );
00192 }
00193
00194 void JobCollection::execute ( Thread *t )
00195 {
00196 REQUIRE ( d->weaver != 0);
00197
00198
00199
00200 emit (started (this));
00201
00202 if ( d->elements->isEmpty() )
00203 {
00204 Job::execute( t );
00205 return;
00206 }
00207
00208 {
00209
00210
00211 QMutexLocker l ( & d->mutex );
00212 d->jobCounter = d->elements->size();
00213
00214
00215 for (int index = 1; index < d->elements->size(); ++index)
00216 {
00217 d->weaver->enqueue (d->elements->at(index));
00218 }
00219 }
00220
00221
00222
00223
00224
00225 d->elements->at( 0 )->execute ( t );
00226
00227
00228
00229
00230
00231 }
00232
00233 Job* JobCollection::jobAt( int i )
00234 {
00235 QMutexLocker l( &d->mutex );
00236 REQUIRE ( i >= 0 && i < d->elements->size() );
00237 return d->elements->at( i )->payload();
00238 }
00239
00240 const int JobCollection::jobListLength()
00241 {
00242 QMutexLocker l( &d->mutex );
00243 return d->elements->size();
00244 }
00245
00246 bool JobCollection::canBeExecuted()
00247 {
00248 bool inheritedCanRun = true;
00249
00250 QMutexLocker l( &d->mutex );
00251
00252 if ( d->elements->size() > 0 )
00253 {
00254 inheritedCanRun = d->elements->at( 0 )->canBeExecuted();
00255 }
00256
00257 return Job::canBeExecuted() && inheritedCanRun;
00258 }
00259
00260 void JobCollection::internalJobDone ( Job* job )
00261 {
00262 REQUIRE (job != 0);
00263 Q_UNUSED (job);
00264
00265 QMutexLocker l( &d->mutex );
00266
00267 if ( d->jobCounter == 0 )
00268 {
00269
00270 d->weaver = 0;
00271 return;
00272 }
00273
00274 --d->jobCounter;
00275
00276 if (d->jobCounter == 0)
00277 {
00278 if (! success())
00279 {
00280 emit failed(this);
00281 }
00282
00283 finalCleanup();
00284 }
00285 ENSURE (d->jobCounter >= 0);
00286 }
00287
00288 void JobCollection::finalCleanup()
00289 {
00290 freeQueuePolicyResources();
00291 setFinished(true);
00292 d->weaver = 0;
00293 emit done(this);
00294 }
00295
00296 void JobCollection::dequeueElements()
00297 {
00298 QMutexLocker l( &d->mutex );
00299
00300 if ( d->weaver != 0 )
00301 {
00302 for ( int index = 1; index < d->elements->size(); ++index )
00303 {
00304 if ( d->elements->at( index ) && ! d->elements->at( index )->isFinished() )
00305 {
00306 debug( 4, "JobCollection::dequeueElements: dequeueing %p.\n",
00307 d->elements->at( index ) );
00308 d->weaver->dequeue ( d->elements->at( index ) );
00309 } else {
00310 debug( 4, "JobCollection::dequeueElements: not dequeueing %p, already finished.\n",
00311 d->elements->at( index ) );
00312 }
00313 }
00314
00315 if (d->jobCounter != 0)
00316 {
00317
00318
00319 finalCleanup();
00320 }
00321 d->jobCounter = 0;
00322 }
00323 }
00324
00325 #include "JobCollection.moc"
00326 #include "JobCollection_p.moc"