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 //}