• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

ThreadWeaver

  • sources
  • kde-4.12
  • kdelibs
  • threadweaver
  • Weaver
JobCollection.cpp
Go to the documentation of this file.
1 /* -*- C++ -*-
2 
3 This file implements the JobCollection class.
4 
5 $ Author: Mirko Boehm $
6 $ Copyright: (C) 2004-2013 Mirko Boehm $
7 $ Contact: mirko@kde.org
8 http://www.kde.org
9 http://creative-destruction.me $
10 
11  This library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU Library General Public
13  License as published by the Free Software Foundation; either
14  version 2 of the License, or (at your option) any later version.
15 
16  This library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  Library General Public License for more details.
20 
21  You should have received a copy of the GNU Library General Public License
22  along with this library; see the file COPYING.LIB. If not, write to
23  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  Boston, MA 02110-1301, USA.
25 
26 $Id: DebuggingAids.h 30 2005-08-16 16:16:04Z mirko $
27 */
28 
29 #include "JobCollection.h"
30 #include "JobCollection_p.h"
31 
32 #include "WeaverInterface.h"
33 #include "DebuggingAids.h"
34 
35 #include <QtCore/QList>
36 #include <QtCore/QObject>
37 #include <QtCore/QPointer>
38 
39 #include "DependencyPolicy.h"
40 
41 using namespace ThreadWeaver;
42 
43 JobCollectionJobRunner::JobCollectionJobRunner ( JobCollection* collection, Job* payload, QObject* parent )
44  : Job( parent )
45  , m_payload( payload )
46  , m_collection( collection )
47 {
48  Q_ASSERT ( payload ); // will not accept zero jobs
49 
50  if ( ! m_payload->objectName().isEmpty() )
51  { // this is most useful for debugging...
52  setObjectName( tr( "JobRunner executing " ) + m_payload->objectName() );
53  } else {
54  setObjectName( tr( "JobRunner (unnamed payload)" ) );
55  }
56 }
57 
58 bool JobCollectionJobRunner::canBeExecuted()
59 { // the JobCollectionJobRunner object never have any dependencies:
60  return m_payload->canBeExecuted();
61 }
62 
63 Job* JobCollectionJobRunner::payload ()
64 {
65  return m_payload;
66 }
67 
68 void JobCollectionJobRunner::aboutToBeQueued ( WeaverInterface *weaver )
69 {
70  m_payload->aboutToBeQueued( weaver );
71 }
72 
73 void JobCollectionJobRunner::aboutToBeDequeued ( WeaverInterface *weaver )
74 {
75  m_payload->aboutToBeDequeued( weaver );
76 }
77 
78 void JobCollectionJobRunner::execute ( Thread *t )
79 {
80  if ( m_payload )
81  {
82  m_payload->execute ( t );
83  m_collection->internalJobDone ( m_payload);
84  } else {
85  debug ( 1, "JobCollection: job in collection has been deleted." );
86  }
87  Job::execute ( t );
88 }
89 
90 int JobCollectionJobRunner::priority () const
91 {
92  return m_payload->priority();
93 }
94 
95 void JobCollectionJobRunner::run ()
96 {
97 }
98 
99 class JobList : public QList <JobCollectionJobRunner*> {};
100 
101 class JobCollection::Private
102 {
103 public:
104 
105  Private()
106  : elements ( new JobList() )
107  , weaver ( 0 )
108  , jobCounter (0)
109  {}
110 
111  ~Private()
112  {
113  delete elements;
114  }
115 
116  /* The elements of the collection. */
117  JobList* elements;
118 
119  /* The Weaver interface this collection is queued in. */
120  WeaverInterface *weaver;
121 
122  /* Counter for the finished jobs.
123  Set to the number of elements when started.
124  When zero, all elements are done.
125  */
126  int jobCounter;
127 
128  QMutex mutex;
129 };
130 
131 JobCollection::JobCollection ( QObject *parent )
132  : Job ( parent )
133  , d (new Private)
134 {
135 }
136 
137 JobCollection::~JobCollection()
138 { // dequeue all remaining jobs:
139  if ( d->weaver != 0 ) // still queued
140  dequeueElements();
141  // QObject cleanup takes care of the job runners
142  delete d;
143 }
144 
145 void JobCollection::addJob ( Job *job )
146 {
147  REQUIRE( d->weaver == 0 );
148  REQUIRE( job != 0);
149 
150  JobCollectionJobRunner* runner = new JobCollectionJobRunner( this, job, this );
151  d->elements->append ( runner );
152  connect( runner , SIGNAL(done(ThreadWeaver::Job*)) , this , SLOT(jobRunnerDone()) );
153 }
154 
155 void JobCollection::stop( Job *job )
156 { // this only works if there is an event queue executed by the main
157  // thread, and it is not blocked:
158  Q_UNUSED( job );
159  if ( d->weaver != 0 )
160  {
161  debug( 4, "JobCollection::stop: dequeueing %p.\n", (void*)this);
162  d->weaver->dequeue( this );
163  }
164  // FIXME ENSURE ( d->weaver == 0 ); // verify that aboutToBeDequeued has been called
165 }
166 
167 void JobCollection::aboutToBeQueued ( WeaverInterface *weaver )
168 {
169  REQUIRE ( d->weaver == 0 ); // never queue twice
170 
171  d->weaver = weaver;
172 
173  if ( d->elements->size() > 0 )
174  {
175  d->elements->at( 0 )->aboutToBeQueued( weaver );
176  }
177 
178  ENSURE(d->weaver != 0);
179 }
180 
181 void JobCollection::aboutToBeDequeued( WeaverInterface* weaver )
182 { // Q_ASSERT ( d->weaver != 0 );
183  // I thought: "must have been queued first"
184  // but the user can queue and dequeue in a suspended Weaver
185 
186  if ( d->weaver )
187  {
188  dequeueElements();
189 
190  if ( !d->elements->isEmpty() )
191  {
192  d->elements->at( 0 )->aboutToBeDequeued( weaver );
193  }
194  }
195 
196  d->weaver = 0;
197  ENSURE ( d->weaver == 0 );
198 }
199 
200 void JobCollection::execute ( Thread *t )
201 {
202  REQUIRE ( d->weaver != 0);
203 
204  // this is async,
205  // JobTests::JobSignalsAreEmittedAsynchronouslyTest() proves it
206  emit (started (this));
207 
208  if ( d->elements->isEmpty() )
209  { // we are just a regular, empty job (sob...):
210  Job::execute( t );
211  return;
212  }
213 
214  { // d->elements is supposedly constant at this time, since we are
215  // already queued
216  // set job counter:
217  QMutexLocker l ( & d->mutex );
218  d->jobCounter = d->elements->size();
219 
220  // queue elements:
221  for (int index = 1; index < d->elements->size(); ++index)
222  {
223  d->weaver->enqueue (d->elements->at(index));
224  }
225  }
226  // this is a hack (but a good one): instead of queueing (this), we
227  // execute the last job, to avoid to have (this) wait for an
228  // available thread (the last operation does not get queued in
229  // aboutToBeQueued() )
230  // NOTE: this also calls internalJobDone()
231  d->elements->at( 0 )->execute ( t );
232 
233  // do not emit done, done is emitted when the last job called
234  // internalJobDone()
235  // also, do not free the queue policies yet, since not the whole job
236  // is done
237 }
238 
239 Job* JobCollection::jobAt( int i )
240 {
241  QMutexLocker l( &d->mutex );
242  REQUIRE ( i >= 0 && i < d->elements->size() );
243  return d->elements->at( i )->payload();
244 }
245 
246 const int JobCollection::jobListLength() // const qualifier is possibly BiC?
247 {
248  QMutexLocker l( &d->mutex );
249  return d->elements->size();
250 }
251 
252 bool JobCollection::canBeExecuted()
253 {
254  bool inheritedCanRun = true;
255 
256  QMutexLocker l( &d->mutex );
257 
258  if ( d->elements->size() > 0 )
259  {
260  inheritedCanRun = d->elements->at( 0 )->canBeExecuted();
261  }
262 
263  return Job::canBeExecuted() && inheritedCanRun;
264 }
265 
266 void JobCollection::jobRunnerDone()
267 {
268  // Note: d->mutex must be unlocked before emitting the done() signal
269  // because this JobCollection may be deleted by a slot connected to done()
270  // in another thread
271  bool emitDone = false;
272 
273  {
274  QMutexLocker l(&d->mutex);
275 
276  if ( d->jobCounter == 0 )
277  { // there is a small chance that (this) has been dequeued in the
278  // meantime, in this case, there is nothing left to clean up:
279  d->weaver = 0;
280  return;
281  }
282 
283  --d->jobCounter;
284 
285  ENSURE (d->jobCounter >= 0);
286 
287  if (d->jobCounter == 0)
288  {
289  if (! success())
290  {
291  emit failed(this);
292  }
293 
294  finalCleanup();
295  emitDone = true;
296  }
297  }
298 
299  if (emitDone)
300  emit done(this);
301 }
302 void JobCollection::internalJobDone ( Job* job )
303 {
304  REQUIRE( job != 0 );
305  Q_UNUSED (job);
306 }
307 
308 void JobCollection::finalCleanup()
309 {
310  freeQueuePolicyResources();
311  setFinished(true);
312  d->weaver = 0;
313 }
314 
315 void JobCollection::dequeueElements()
316 {
317  // Note: d->mutex must be unlocked before emitting the done() signal
318  // because this JobCollection may be deleted by a slot connected to done() in another
319  // thread
320 
321  bool emitDone = false;
322 
323  {
324  // dequeue everything:
325  QMutexLocker l( &d->mutex );
326 
327  if ( d->weaver != 0 )
328  {
329  for ( int index = 1; index < d->elements->size(); ++index )
330  {
331  if ( d->elements->at( index ) && ! d->elements->at( index )->isFinished() ) // ... a QPointer
332  {
333  debug( 4, "JobCollection::dequeueElements: dequeueing %p.\n",
334  (void*)d->elements->at( index ) );
335  d->weaver->dequeue ( d->elements->at( index ) );
336  } else {
337  debug( 4, "JobCollection::dequeueElements: not dequeueing %p, already finished.\n",
338  (void*)d->elements->at( index ) );
339  }
340  }
341 
342  if (d->jobCounter != 0)
343  { // if jobCounter is not zero, then we where waiting for the
344  // last job to finish before we would have freed our queue
345  // policies, but in this case we have to do it here:
346  finalCleanup();
347  }
348  d->jobCounter = 0;
349  }
350  }
351  if (emitDone)
352  emit done(this);
353 }
354 
355 #include "JobCollection.moc"
356 #include "JobCollection_p.moc"
ThreadWeaver::Job::done
void done(ThreadWeaver::Job *)
This signal is emitted when the job has been finished (no matter if it succeeded or not)...
ThreadWeaver::JobCollectionJobRunner::aboutToBeDequeued
void aboutToBeDequeued(WeaverInterface *weaver)
This Job is about the be dequeued from the weaver's job queue.
Definition: JobCollection.cpp:73
JobCollection.h
DependencyPolicy.h
ThreadWeaver::JobCollectionJobRunner::payload
Job * payload()
Definition: JobCollection.cpp:63
ThreadWeaver::JobCollection::internalJobDone
virtual void internalJobDone(Job *)
Callback method for done jobs.
Definition: JobCollection.cpp:302
ThreadWeaver::JobCollection::jobListLength
const int jobListLength()
Return the number of jobs in the joblist.
Definition: JobCollection.cpp:246
ThreadWeaver::Thread
The class Thread is used to represent the worker threads in the weaver's inventory.
Definition: Thread.h:46
JobCollection_p.h
QObject
ThreadWeaver::Job::success
virtual bool success() const
Return whether the Job finished successfully or not.
Definition: Job.cpp:144
REQUIRE
#define REQUIRE(x)
Definition: DebuggingAids.h:146
ThreadWeaver::JobCollectionJobRunner::canBeExecuted
bool canBeExecuted()
canBeExecuted() returns true if all the jobs queue policies agree to it.
Definition: JobCollection.cpp:58
ThreadWeaver::JobCollectionJobRunner::aboutToBeQueued
void aboutToBeQueued(WeaverInterface *weaver)
The job is about to be added to the weaver's job queue.
Definition: JobCollection.cpp:68
ThreadWeaver::JobCollection::addJob
virtual void addJob(Job *)
Append a job to the collection.
Definition: JobCollection.cpp:145
ThreadWeaver::Job::execute
virtual void execute(Thread *)
Perform the job.
Definition: Job.cpp:122
ThreadWeaver::JobCollection::canBeExecuted
bool canBeExecuted()
Overload to manage recursive sets.
Definition: JobCollection.cpp:252
ThreadWeaver::Job::started
void started(ThreadWeaver::Job *)
This signal is emitted when this job is being processed by a thread.
ENSURE
#define ENSURE(x)
Definition: DebuggingAids.h:150
DebuggingAids.h
ThreadWeaver::Job::failed
void failed(ThreadWeaver::Job *)
This job has failed.
ThreadWeaver::JobCollectionJobRunner::execute
void execute(Thread *t)
Perform the job.
Definition: JobCollection.cpp:78
ThreadWeaver::Job::freeQueuePolicyResources
void freeQueuePolicyResources()
Free the queue policies acquired before this job has been executed.
Definition: Job.cpp:149
ThreadWeaver::JobCollection::~JobCollection
~JobCollection()
Definition: JobCollection.cpp:137
ThreadWeaver::Job::setFinished
void setFinished(bool status)
Call with status = true to mark this job as done.
Definition: Job.cpp:230
ThreadWeaver::debug
void debug(int severity, const char *cformat,...)
This method prints a text message on the screen, if debugging is enabled.
Definition: DebuggingAids.h:112
ThreadWeaver::JobCollection::stop
void stop(ThreadWeaver::Job *job)
Stop processing, dequeue all remaining Jobs.
Definition: JobCollection.cpp:155
ThreadWeaver::JobCollection::aboutToBeDequeued
void aboutToBeDequeued(WeaverInterface *weaver)
Overload to dequeue the collection.
Definition: JobCollection.cpp:181
ThreadWeaver::JobCollection::aboutToBeQueued
void aboutToBeQueued(WeaverInterface *weaver)
Overload to queue the collection.
Definition: JobCollection.cpp:167
ThreadWeaver::Job::canBeExecuted
virtual bool canBeExecuted()
canBeExecuted() returns true if all the jobs queue policies agree to it.
Definition: Job.cpp:165
ThreadWeaver::JobCollection::jobAt
Job * jobAt(int i)
Return a reference to the job in the job list at position i.
Definition: JobCollection.cpp:239
ThreadWeaver::JobCollection::finalCleanup
void finalCleanup()
Perform the task usually done when one individual job is finished, but in our case only when the whol...
Definition: JobCollection.cpp:308
ThreadWeaver::JobCollectionJobRunner::priority
int priority() const
The queueing priority of the job.
Definition: JobCollection.cpp:90
ThreadWeaver::WeaverInterface
WeaverInterface provides a common interface for weaver implementations.
Definition: WeaverInterface.h:61
WeaverInterface.h
ThreadWeaver::JobCollection
A JobCollection is a vector of Jobs that will be queued together.
Definition: JobCollection.h:49
ThreadWeaver::Job
A Job is a simple abstraction of an action that is to be executed in a thread context.
Definition: Job.h:65
ThreadWeaver::JobCollectionJobRunner
Definition: JobCollection_p.h:45
ThreadWeaver::JobCollection::JobCollection
JobCollection(QObject *parent=0)
Definition: JobCollection.cpp:131
ThreadWeaver::JobCollection::JobCollectionJobRunner
friend class JobCollectionJobRunner
Definition: JobCollection.h:51
QList
Definition: DependencyPolicy.h:32
ThreadWeaver::JobCollectionJobRunner::JobCollectionJobRunner
JobCollectionJobRunner(JobCollection *collection, Job *payload, QObject *parent)
Definition: JobCollection.cpp:43
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:53 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

ThreadWeaver

Skip menu "ThreadWeaver"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal