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

ThreadWeaver

  • threadweaver
  • Weaver
JobCollection.cpp
Go to the documentation of this file.
1/* -*- C++ -*-
2
3This file implements the JobCollection class.
4
5$ Author: Mirko Boehm $
6$ Copyright: (C) 2004-2013 Mirko Boehm $
7$ Contact: mirko@kde.org
8http://www.kde.org
9http://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
41using namespace ThreadWeaver;
42
43JobCollectionJobRunner::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
58bool JobCollectionJobRunner::canBeExecuted()
59{ // the JobCollectionJobRunner object never have any dependencies:
60 return m_payload->canBeExecuted();
61}
62
63Job* JobCollectionJobRunner::payload ()
64{
65 return m_payload;
66}
67
68void JobCollectionJobRunner::aboutToBeQueued ( WeaverInterface *weaver )
69{
70 m_payload->aboutToBeQueued( weaver );
71}
72
73void JobCollectionJobRunner::aboutToBeDequeued ( WeaverInterface *weaver )
74{
75 m_payload->aboutToBeDequeued( weaver );
76}
77
78void 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
90int JobCollectionJobRunner::priority () const
91{
92 return m_payload->priority();
93}
94
95void JobCollectionJobRunner::run ()
96{
97}
98
99class JobList : public QList <JobCollectionJobRunner*> {};
100
101class JobCollection::Private
102{
103public:
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
131JobCollection::JobCollection ( QObject *parent )
132 : Job ( parent )
133 , d (new Private)
134{
135}
136
137JobCollection::~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
145void 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
155void 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
167void 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
181void 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
200void 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
239Job* 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
246const int JobCollection::jobListLength() // const qualifier is possibly BiC?
247{
248 QMutexLocker l( &d->mutex );
249 return d->elements->size();
250}
251
252bool 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
266void 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}
302void JobCollection::internalJobDone ( Job* job )
303{
304 REQUIRE( job != 0 );
305 Q_UNUSED (job);
306}
307
308void JobCollection::finalCleanup()
309{
310 freeQueuePolicyResources();
311 setFinished(true);
312 d->weaver = 0;
313}
314
315void 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"
DebuggingAids.h
ENSURE
#define ENSURE(x)
Definition: DebuggingAids.h:150
REQUIRE
#define REQUIRE(x)
Definition: DebuggingAids.h:146
DependencyPolicy.h
JobCollection.h
JobCollection_p.h
WeaverInterface.h
QList
Definition: DependencyPolicy.h:32
QObject
ThreadWeaver::JobCollectionJobRunner
Definition: JobCollection_p.h:46
ThreadWeaver::JobCollectionJobRunner::canBeExecuted
bool canBeExecuted()
canBeExecuted() returns true if all the jobs queue policies agree to it.
Definition: JobCollection.cpp:58
ThreadWeaver::JobCollectionJobRunner::aboutToBeDequeued
void aboutToBeDequeued(WeaverInterface *weaver)
This Job is about the be dequeued from the weaver's job queue.
Definition: JobCollection.cpp:73
ThreadWeaver::JobCollectionJobRunner::priority
int priority() const
The queueing priority of the job.
Definition: JobCollection.cpp:90
ThreadWeaver::JobCollectionJobRunner::payload
Job * payload()
Definition: JobCollection.cpp:63
ThreadWeaver::JobCollectionJobRunner::execute
void execute(Thread *t)
Perform the job.
Definition: JobCollection.cpp:78
ThreadWeaver::JobCollectionJobRunner::JobCollectionJobRunner
JobCollectionJobRunner(JobCollection *collection, Job *payload, QObject *parent)
Definition: JobCollection.cpp:43
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
A JobCollection is a vector of Jobs that will be queued together.
Definition: JobCollection.h:50
ThreadWeaver::JobCollection::stop
void stop(ThreadWeaver::Job *job)
Stop processing, dequeue all remaining Jobs.
Definition: JobCollection.cpp:155
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::jobListLength
const int jobListLength()
Return the number of jobs in the joblist.
Definition: JobCollection.cpp:246
ThreadWeaver::JobCollection::internalJobDone
virtual void internalJobDone(Job *)
Callback method for done jobs.
Definition: JobCollection.cpp:302
ThreadWeaver::JobCollection::~JobCollection
~JobCollection()
Definition: JobCollection.cpp:137
ThreadWeaver::JobCollection::addJob
virtual void addJob(Job *)
Append a job to the collection.
Definition: JobCollection.cpp:145
ThreadWeaver::JobCollection::aboutToBeQueued
void aboutToBeQueued(WeaverInterface *weaver)
Overload to queue the collection.
Definition: JobCollection.cpp:167
ThreadWeaver::JobCollection::JobCollectionJobRunner
friend class JobCollectionJobRunner
Definition: JobCollection.h:51
ThreadWeaver::JobCollection::aboutToBeDequeued
void aboutToBeDequeued(WeaverInterface *weaver)
Overload to dequeue the collection.
Definition: JobCollection.cpp:181
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::JobCollection::JobCollection
JobCollection(QObject *parent=0)
Definition: JobCollection.cpp:131
ThreadWeaver::JobCollection::canBeExecuted
bool canBeExecuted()
Overload to manage recursive sets.
Definition: JobCollection.cpp:252
ThreadWeaver::Job
A Job is a simple abstraction of an action that is to be executed in a thread context.
Definition: Job.h:66
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::Job::success
virtual bool success() const
Return whether the Job finished successfully or not.
Definition: Job.cpp:144
ThreadWeaver::Job::execute
virtual void execute(Thread *)
Perform the job.
Definition: Job.cpp:122
ThreadWeaver::Job::failed
void failed(ThreadWeaver::Job *)
This job has failed.
ThreadWeaver::Job::freeQueuePolicyResources
void freeQueuePolicyResources()
Free the queue policies acquired before this job has been executed.
Definition: Job.cpp:149
ThreadWeaver::Job::canBeExecuted
virtual bool canBeExecuted()
canBeExecuted() returns true if all the jobs queue policies agree to it.
Definition: Job.cpp:165
ThreadWeaver::Job::started
void started(ThreadWeaver::Job *)
This signal is emitted when this job is being processed by a thread.
ThreadWeaver::Job::setFinished
void setFinished(bool status)
Call with status = true to mark this job as done.
Definition: Job.cpp:230
ThreadWeaver::Thread
The class Thread is used to represent the worker threads in the weaver's inventory.
Definition: Thread.h:47
ThreadWeaver::WeaverInterface
WeaverInterface provides a common interface for weaver implementations.
Definition: WeaverInterface.h:61
ThreadWeaver
Definition: DebuggingAids.h:51
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
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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