Warning, file /frameworks/threadweaver/src/dependencypolicy.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* -*- C++ -*- 0002 This file implements the DependencyPolicy class. 0003 0004 SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <mirko@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 0008 $Id: DebuggingAids.cpp 20 2005-08-08 21:02:51Z mirko $ 0009 */ 0010 0011 #include "dependencypolicy.h" 0012 0013 #include <QCoreApplication> 0014 #include <QDebug> 0015 #include <QMutex> 0016 0017 #include "debuggingaids.h" 0018 #include "job.h" 0019 #include "managedjobpointer.h" 0020 0021 #include "dependency.h" 0022 0023 using namespace ThreadWeaver; 0024 0025 typedef QMultiMap<JobPointer, JobPointer> JobMultiMap; 0026 0027 class Q_DECL_HIDDEN DependencyPolicy::Private 0028 { 0029 public: 0030 /** A container to keep track of Job dependencies. 0031 * For each dependency A->B, which means Job B depends on Job A and may only be executed after A has been 0032 * finished, an entry will be added with key A and value B. When A is finished, the entry will be removed. 0033 */ 0034 JobMultiMap &dependencies() 0035 { 0036 return depMap_; 0037 } 0038 0039 QMutex *mutex() 0040 { 0041 return &mutex_; 0042 } 0043 0044 JobMultiMap depMap_; 0045 QMutex mutex_; 0046 }; 0047 0048 DependencyPolicy::DependencyPolicy() 0049 : QueuePolicy() 0050 , d(new Private()) 0051 { 0052 } 0053 0054 DependencyPolicy::~DependencyPolicy() 0055 { 0056 delete d; 0057 } 0058 0059 void DependencyPolicy::addDependency(JobPointer jobA, JobPointer jobB) 0060 { 0061 // jobA depends on jobB 0062 REQUIRE(jobA != nullptr && jobB != nullptr && jobA != jobB); 0063 0064 QMutexLocker a(jobA->mutex()); 0065 QMutexLocker b(jobB->mutex()); 0066 QMutexLocker l(d->mutex()); 0067 jobA->assignQueuePolicy(this); 0068 jobB->assignQueuePolicy(this); 0069 d->dependencies().insert(jobA, jobB); 0070 TWDEBUG(2, "inserted dependency %p->%p.\n", jobA.data(), jobB.data()); 0071 ENSURE(d->dependencies().contains(jobA)); 0072 } 0073 0074 void DependencyPolicy::addDependency(const Dependency &dep) 0075 { 0076 addDependency(dep.dependent(), dep.dependee()); 0077 } 0078 0079 bool DependencyPolicy::removeDependency(JobPointer jobA, JobPointer jobB) 0080 { 0081 REQUIRE(jobA != nullptr && jobB != nullptr); 0082 bool result = false; 0083 QMutexLocker l(d->mutex()); 0084 0085 // there may be only one (!) occurrence of [this, dep]: 0086 QMutableMultiMapIterator<JobPointer, JobPointer> it(d->dependencies()); 0087 while (it.hasNext()) { 0088 it.next(); 0089 if (it.key() == jobA && it.value() == jobB) { 0090 it.remove(); 0091 TWDEBUG(2, "removed dependency %p->%p.\n", jobA.data(), jobB.data()); 0092 result = true; 0093 break; 0094 } 0095 } 0096 TWDEBUG(result == false, 2, "cannot remove dependency %p->%p, not found.\n", jobA.data(), jobB.data()); 0097 ENSURE(!d->dependencies().keys(jobB).contains(jobA)); 0098 return result; 0099 } 0100 0101 bool DependencyPolicy::removeDependency(const Dependency &dep) 0102 { 0103 return removeDependency(dep.dependent(), dep.dependee()); 0104 } 0105 0106 void DependencyPolicy::resolveDependencies(JobPointer job) 0107 { 0108 if (job->success()) { 0109 QMutexLocker l(d->mutex()); 0110 QMutableMultiMapIterator<JobPointer, JobPointer> it(d->dependencies()); 0111 // there has to be a better way to do this: (?) 0112 while (it.hasNext()) { // we remove all entries where jobs depend on *this* : 0113 it.next(); 0114 if (it.value() == job) { 0115 TWDEBUG(2, "resolved dependencies for %p: %p->%p.\n", job.data(), it.key().data(), it.value().data()); 0116 it.remove(); 0117 } 0118 } 0119 } 0120 } 0121 0122 // QList<JobPointer> DependencyPolicy::getDependencies(JobPointer job) const 0123 //{ 0124 // REQUIRE (job != 0); 0125 // QList<JobInterface*> result; 0126 // JobMultiMap::const_iterator it; 0127 // QMutexLocker l( & d->mutex() ); 0128 0129 // for ( it = d->dependencies().constBegin(); it != d->dependencies().constEnd(); ++it ) 0130 // { 0131 // if ( it.key() == job ) 0132 // { 0133 // result.append( it.value() ); 0134 // } 0135 // } 0136 // return result; 0137 //} 0138 0139 bool DependencyPolicy::hasUnresolvedDependencies(JobPointer job) const 0140 { 0141 REQUIRE(job != nullptr); 0142 QMutexLocker l(d->mutex()); 0143 return d->dependencies().contains(job); 0144 } 0145 0146 bool DependencyPolicy::isEmpty() const 0147 { 0148 QMutexLocker l(d->mutex()); 0149 return d->dependencies().isEmpty(); 0150 } 0151 0152 DependencyPolicy &DependencyPolicy::instance() 0153 { 0154 static DependencyPolicy policy; 0155 return policy; 0156 } 0157 0158 bool DependencyPolicy::canRun(JobPointer job) 0159 { 0160 REQUIRE(job != nullptr); 0161 return !hasUnresolvedDependencies(job); 0162 } 0163 0164 void DependencyPolicy::free(JobPointer job) 0165 { 0166 REQUIRE(job != nullptr); 0167 REQUIRE(job->status() > Job::Status_Running); 0168 if (job->success()) { 0169 resolveDependencies(job); 0170 TWDEBUG(3, "DependencyPolicy::free: dependencies resolved for job %p.\n", (void *)job.data()); 0171 } else { 0172 TWDEBUG(3, "DependencyPolicy::free: not resolving dependencies for %p (execution not successful).\n", (void *)job.data()); 0173 } 0174 ENSURE((!hasUnresolvedDependencies(job) && job->success()) || !job->success()); 0175 } 0176 0177 void DependencyPolicy::release(JobPointer job) 0178 { 0179 REQUIRE(job != nullptr); 0180 Q_UNUSED(job) 0181 } 0182 0183 void DependencyPolicy::destructed(JobInterface *job) 0184 { 0185 REQUIRE(job != nullptr); 0186 resolveDependencies(ManagedJobPointer<JobInterface>(job)); 0187 } 0188 0189 // void DependencyPolicy::dumpJobDependencies() 0190 //{ 0191 // QMutexLocker l( & d->mutex() ); 0192 0193 // debug ( 0, "Job Dependencies (left depends on right side):\n" ); 0194 // for ( JobMultiMap::const_iterator it = d->dependencies().constBegin(); it != d->dependencies().constEnd(); ++it ) 0195 // { 0196 // debug( 0, " : %p <-- %p\n", (void*)it.key(), (void*)it.value()); 0197 // } 0198 // debug ( 0, "-----------------\n" ); 0199 //}