ThreadWeaver

dependencypolicy.cpp
1/* -*- C++ -*-
2 This file implements the DependencyPolicy class.
3
4 SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <mirko@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7
8 $Id: DebuggingAids.cpp 20 2005-08-08 21:02:51Z mirko $
9*/
10
11#include "dependencypolicy.h"
12
13#include <QCoreApplication>
14#include <QDebug>
15#include <QMutex>
16
17#include "debuggingaids.h"
18#include "job.h"
19#include "managedjobpointer.h"
20
21#include "dependency.h"
22
23using namespace ThreadWeaver;
24
26
27class Q_DECL_HIDDEN DependencyPolicy::Private
28{
29public:
30 /** A container to keep track of Job dependencies.
31 * For each dependency A->B, which means Job B depends on Job A and may only be executed after A has been
32 * finished, an entry will be added with key A and value B. When A is finished, the entry will be removed.
33 */
34 JobMultiMap &dependencies()
35 {
36 return depMap_;
37 }
38
39 QMutex *mutex()
40 {
41 return &mutex_;
42 }
43
44 JobMultiMap depMap_;
45 QMutex mutex_;
46};
47
48DependencyPolicy::DependencyPolicy()
49 : QueuePolicy()
50 , d(new Private())
51{
52}
53
58
60{
61 // jobA depends on jobB
62 REQUIRE(jobA != nullptr && jobB != nullptr && jobA != jobB);
63
64 QMutexLocker a(jobA->mutex());
65 QMutexLocker b(jobB->mutex());
66 QMutexLocker l(d->mutex());
67 jobA->assignQueuePolicy(this);
68 jobB->assignQueuePolicy(this);
69 d->dependencies().insert(jobA, jobB);
70 TWDEBUG(2, "inserted dependency %p->%p.\n", jobA.data(), jobB.data());
71 ENSURE(d->dependencies().contains(jobA));
72}
73
74void DependencyPolicy::addDependency(const Dependency &dep)
75{
76 addDependency(dep.dependent(), dep.dependee());
77}
78
80{
81 REQUIRE(jobA != nullptr && jobB != nullptr);
82 bool result = false;
83 QMutexLocker l(d->mutex());
84
85 // there may be only one (!) occurrence of [this, dep]:
87 while (it.hasNext()) {
88 it.next();
89 if (it.key() == jobA && it.value() == jobB) {
90 it.remove();
91 TWDEBUG(2, "removed dependency %p->%p.\n", jobA.data(), jobB.data());
92 result = true;
93 break;
94 }
95 }
96 TWDEBUG(result == false, 2, "cannot remove dependency %p->%p, not found.\n", jobA.data(), jobB.data());
97 ENSURE(!d->dependencies().keys(jobB).contains(jobA));
98 return result;
99}
100
101bool DependencyPolicy::removeDependency(const Dependency &dep)
102{
103 return removeDependency(dep.dependent(), dep.dependee());
104}
105
107{
108 if (job->success()) {
109 QMutexLocker l(d->mutex());
111 // there has to be a better way to do this: (?)
112 while (it.hasNext()) { // we remove all entries where jobs depend on *this* :
113 it.next();
114 if (it.value() == job) {
115 TWDEBUG(2, "resolved dependencies for %p: %p->%p.\n", job.data(), it.key().data(), it.value().data());
116 it.remove();
117 }
118 }
119 }
120}
121
122// QList<JobPointer> DependencyPolicy::getDependencies(JobPointer job) const
123//{
124// REQUIRE (job != 0);
125// QList<JobInterface*> result;
126// JobMultiMap::const_iterator it;
127// QMutexLocker l( & d->mutex() );
128
129// for ( it = d->dependencies().constBegin(); it != d->dependencies().constEnd(); ++it )
130// {
131// if ( it.key() == job )
132// {
133// result.append( it.value() );
134// }
135// }
136// return result;
137//}
138
140{
141 REQUIRE(job != nullptr);
142 QMutexLocker l(d->mutex());
143 return d->dependencies().contains(job);
144}
145
146bool DependencyPolicy::isEmpty() const
147{
148 QMutexLocker l(d->mutex());
149 return d->dependencies().isEmpty();
150}
151
152DependencyPolicy &DependencyPolicy::instance()
153{
154 static DependencyPolicy policy;
155 return policy;
156}
157
159{
160 REQUIRE(job != nullptr);
161 return !hasUnresolvedDependencies(job);
162}
163
165{
166 REQUIRE(job != nullptr);
167 REQUIRE(job->status() > Job::Status_Running);
168 if (job->success()) {
170 TWDEBUG(3, "DependencyPolicy::free: dependencies resolved for job %p.\n", (void *)job.data());
171 } else {
172 TWDEBUG(3, "DependencyPolicy::free: not resolving dependencies for %p (execution not successful).\n", (void *)job.data());
173 }
174 ENSURE((!hasUnresolvedDependencies(job) && job->success()) || !job->success());
175}
176
178{
179 REQUIRE(job != nullptr);
180 Q_UNUSED(job)
181}
182
183void DependencyPolicy::destructed(JobInterface *job)
184{
185 REQUIRE(job != nullptr);
186 resolveDependencies(ManagedJobPointer<JobInterface>(job));
187}
188
189// void DependencyPolicy::dumpJobDependencies()
190//{
191// QMutexLocker l( & d->mutex() );
192
193// debug ( 0, "Job Dependencies (left depends on right side):\n" );
194// for ( JobMultiMap::const_iterator it = d->dependencies().constBegin(); it != d->dependencies().constEnd(); ++it )
195// {
196// debug( 0, " : %p <-- %p\n", (void*)it.key(), (void*)it.value());
197// }
198// debug ( 0, "-----------------\n" );
199//}
DependencyPolicy implements execution-time dependencies dependencies between Jobs.
bool removeDependency(JobPointer jobA, JobPointer jobB)
Remove a dependency.
bool hasUnresolvedDependencies(JobPointer) const
Query whether the job has an unresolved dependency.
bool canRun(JobPointer) override
canRun() is called before the job is executed.
~DependencyPolicy() override
Destructor.
void resolveDependencies(JobPointer)
Resolve all dependencies for a job.
void addDependency(JobPointer jobA, JobPointer jobB)
Add jobB as a dependency of jobA.
void destructed(JobInterface *job) override
destructing() is called when a Job that has this queue policy assigned gets destructed.
void release(JobPointer) override
release() is called if canRun() returned true, but the job has not been executed for external reasons...
void free(JobPointer) override
free() is called after the job has been executed.
QueuePolicy is an interface for customizations of the queueing behaviour of jobs.
Definition queuepolicy.h:39
bool contains(const Key &key) const const
iterator insert(const Key &key, const T &value)
bool isEmpty() const const
QList< Key > keys() const const
bool hasNext() const const
const Key & key() const const
T * data() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:31 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.