File indexing completed on 2024-04-21 04:01:29

0001 /* -*- C++ -*-
0002     This file is part of ThreadWeaver.
0003 
0004     SPDX-FileCopyrightText: 2005-2013 Mirko Boehm <mirko@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include <QMutexLocker>
0010 
0011 #include "debuggingaids.h"
0012 #include "destructedstate.h"
0013 #include "inconstructionstate.h"
0014 #include "queuepolicy.h"
0015 #include "shuttingdownstate.h"
0016 #include "suspendedstate.h"
0017 #include "suspendingstate.h"
0018 #include "weaver_p.h"
0019 #include "workinghardstate.h"
0020 
0021 namespace ThreadWeaver
0022 {
0023 namespace Private
0024 {
0025 Weaver_Private::Weaver_Private()
0026     : QueueSignals_Private()
0027     , active(0)
0028     , inventoryMax(qMax(4, 2 * QThread::idealThreadCount()))
0029     , mutex(new QMutex)
0030 
0031 {
0032 }
0033 
0034 Weaver_Private::~Weaver_Private()
0035 {
0036     // FIXME no need for dynamic allocation
0037     delete mutex;
0038 }
0039 
0040 /** @brief Dump the current jobs to the console.
0041  *
0042  * Use at your own risk.
0043  */
0044 void Weaver_Private::dumpJobs()
0045 {
0046     QMutexLocker l(mutex);
0047     Q_UNUSED(l);
0048     TWDEBUG(0, "WeaverImpl::dumpJobs: current jobs:\n");
0049     for (int index = 0; index < assignments.size(); ++index) {
0050         TWDEBUG(0,
0051                 "--> %4i: %p (priority %i, can be executed: %s)\n",
0052                 index,
0053                 (void *)assignments.at(index).data(),
0054                 assignments.at(index)->priority(),
0055                 canBeExecuted(assignments.at(index)) ? "yes" : "no");
0056     }
0057 }
0058 
0059 /** @brief Check with the assigned queue policies if the job can be executed.
0060  *
0061  * If it returns true, it expects that the job is executed right after that. The done() methods of the
0062  * queue policies will be automatically called when the job is finished.
0063  *
0064  * If it returns false, all queue policy resources have been freed, and the method can be called again
0065  * at a later time.
0066  */
0067 bool Weaver_Private::canBeExecuted(JobPointer job)
0068 {
0069     Q_ASSERT(!mutex->tryLock()); // mutex has to be held when this method is called
0070 
0071     QList<QueuePolicy *> acquired;
0072 
0073     bool success = true;
0074 
0075     QMutexLocker l(job->mutex());
0076     QList<QueuePolicy *> policies = job->queuePolicies();
0077     if (!policies.isEmpty()) {
0078         TWDEBUG(4, "WeaverImpl::canBeExecuted: acquiring permission from %i queue %s.\n", policies.size(), policies.size() == 1 ? "policy" : "policies");
0079         for (int index = 0; index < policies.size(); ++index) {
0080             if (policies.at(index)->canRun(job)) {
0081                 acquired.append(policies.at(index));
0082             } else {
0083                 success = false;
0084                 break;
0085             }
0086         }
0087 
0088         TWDEBUG(4, "WeaverImpl::canBeExecuted: queue policies returned %s.\n", success ? "true" : "false");
0089 
0090         if (!success) {
0091             for (int index = 0; index < acquired.size(); ++index) {
0092                 acquired.at(index)->release(job);
0093             }
0094         }
0095     } else {
0096         TWDEBUG(4, "WeaverImpl::canBeExecuted: no queue policies, this job can be executed.\n");
0097     }
0098     return success;
0099 }
0100 
0101 void Weaver_Private::deleteExpiredThreads()
0102 {
0103     Q_ASSERT(!mutex->tryLock()); // mutex has to be held when this method is called
0104     for (Thread *thread : std::as_const(expiredThreads)) {
0105         thread->wait();
0106         delete thread;
0107     }
0108     expiredThreads.clear();
0109 }
0110 
0111 }
0112 
0113 }