File indexing completed on 2024-04-28 11:44:19

0001 /*
0002     SPDX-FileCopyrightText: 2007, 2009 Ryan P. Bitanga <ryan.bitanga@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "runnerjobs_p.h"
0008 
0009 #include <QMutexLocker>
0010 #include <QTimer>
0011 
0012 #include "krunner_debug.h"
0013 #include "querymatch.h"
0014 #include "runnermanager.h"
0015 
0016 using ThreadWeaver::Job;
0017 using ThreadWeaver::Queue;
0018 
0019 namespace Plasma
0020 {
0021 #if KRUNNER_BUILD_DEPRECATED_SINCE(5, 81)
0022 DelayedRunnerPolicy::DelayedRunnerPolicy()
0023     : QueuePolicy()
0024 {
0025 }
0026 
0027 DelayedRunnerPolicy::~DelayedRunnerPolicy()
0028 {
0029 }
0030 
0031 DelayedRunnerPolicy &DelayedRunnerPolicy::instance()
0032 {
0033     static DelayedRunnerPolicy policy;
0034     return policy;
0035 }
0036 
0037 bool DelayedRunnerPolicy::canRun(ThreadWeaver::JobPointer job)
0038 {
0039     QSharedPointer<FindMatchesJob> aJob(job.dynamicCast<FindMatchesJob>());
0040     if (QTimer *t = aJob->delayTimer()) {
0041         // If the timer is active, the required delay has not been reached
0042         return !t->isActive(); // DATA RACE!  (with QTimer start/stop from runnermanager.cpp)
0043     }
0044 
0045     return true;
0046 }
0047 
0048 void DelayedRunnerPolicy::free(ThreadWeaver::JobPointer job)
0049 {
0050     Q_UNUSED(job)
0051 }
0052 
0053 void DelayedRunnerPolicy::release(ThreadWeaver::JobPointer job)
0054 {
0055     free(job);
0056 }
0057 
0058 void DelayedRunnerPolicy::destructed(ThreadWeaver::JobInterface *job)
0059 {
0060     Q_UNUSED(job)
0061 }
0062 #endif
0063 
0064 DefaultRunnerPolicy::DefaultRunnerPolicy()
0065     : QueuePolicy()
0066     , m_cap(2)
0067 {
0068 }
0069 
0070 DefaultRunnerPolicy::~DefaultRunnerPolicy()
0071 {
0072 }
0073 
0074 DefaultRunnerPolicy &DefaultRunnerPolicy::instance()
0075 {
0076     static DefaultRunnerPolicy policy;
0077     return policy;
0078 }
0079 
0080 bool DefaultRunnerPolicy::canRun(ThreadWeaver::JobPointer job)
0081 {
0082     Plasma::AbstractRunner *runner = job.dynamicCast<FindMatchesJob>()->runner();
0083     QMutexLocker l(&m_mutex);
0084 
0085     if (m_runCounts[runner->name()] > m_cap) {
0086         return false;
0087     } else {
0088         ++m_runCounts[runner->name()];
0089         return true;
0090     }
0091 }
0092 
0093 void DefaultRunnerPolicy::free(ThreadWeaver::JobPointer job)
0094 {
0095     Plasma::AbstractRunner *runner = job.dynamicCast<FindMatchesJob>()->runner();
0096     QMutexLocker l(&m_mutex);
0097 
0098     --m_runCounts[runner->name()];
0099 }
0100 
0101 void DefaultRunnerPolicy::release(ThreadWeaver::JobPointer job)
0102 {
0103     free(job);
0104 }
0105 
0106 void DefaultRunnerPolicy::destructed(ThreadWeaver::JobInterface *job)
0107 {
0108     Q_UNUSED(job)
0109 }
0110 
0111 ////////////////////
0112 // Jobs
0113 ////////////////////
0114 
0115 FindMatchesJob::FindMatchesJob(Plasma::AbstractRunner *runner, Plasma::RunnerContext *context, QObject *)
0116     : ThreadWeaver::Job()
0117     , m_context(*context, nullptr)
0118     , m_runner(runner)
0119 {
0120     QMutexLocker l(mutex());
0121     Q_UNUSED(l);
0122 #if KRUNNER_BUILD_DEPRECATED_SINCE(5, 81)
0123     if (runner->speed() == Plasma::AbstractRunner::SlowSpeed) {
0124         assignQueuePolicy(&DelayedRunnerPolicy::instance());
0125     } else {
0126         assignQueuePolicy(&DefaultRunnerPolicy::instance());
0127     }
0128 #else
0129     assignQueuePolicy(&DefaultRunnerPolicy::instance());
0130 #endif
0131 }
0132 
0133 FindMatchesJob::~FindMatchesJob()
0134 {
0135 }
0136 
0137 void FindMatchesJob::run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *)
0138 {
0139     if (m_context.isValid()) {
0140         m_runner->match(m_context);
0141     }
0142     Q_EMIT done(self);
0143 }
0144 
0145 int FindMatchesJob::priority() const
0146 {
0147     return m_runner->priority();
0148 }
0149 
0150 Plasma::AbstractRunner *FindMatchesJob::runner() const
0151 {
0152     return m_runner;
0153 }
0154 
0155 DelayedJobCleaner::DelayedJobCleaner(const QSet<QSharedPointer<FindMatchesJob>> &jobs, const QSet<AbstractRunner *> &runners)
0156     : QObject(Queue::instance())
0157     , m_weaver(Queue::instance())
0158     , m_jobs(jobs)
0159     , m_runners(runners)
0160 {
0161     connect(m_weaver, &ThreadWeaver::QueueSignals::finished, this, &DelayedJobCleaner::checkIfFinished);
0162 
0163     for (auto it = m_jobs.constBegin(); it != m_jobs.constEnd(); ++it) {
0164         connect(it->data(), &FindMatchesJob::done, this, &DelayedJobCleaner::jobDone);
0165     }
0166 }
0167 
0168 DelayedJobCleaner::~DelayedJobCleaner()
0169 {
0170     qDeleteAll(m_runners);
0171 }
0172 
0173 void DelayedJobCleaner::jobDone(ThreadWeaver::JobPointer job)
0174 {
0175     auto runJob = job.dynamicCast<FindMatchesJob>();
0176 
0177     if (!runJob) {
0178         return;
0179     }
0180 
0181     m_jobs.remove(runJob);
0182 
0183     if (m_jobs.isEmpty()) {
0184         deleteLater();
0185     }
0186 }
0187 
0188 void DelayedJobCleaner::checkIfFinished()
0189 {
0190     if (m_weaver->isIdle()) {
0191         m_jobs.clear();
0192         deleteLater();
0193     }
0194 }
0195 
0196 } // Plasma namespace
0197 
0198 #include "moc_runnerjobs_p.cpp"