diff --git a/abstractrunner.cpp b/abstractrunner.cpp index b9593af47..6c56ea1e9 100644 --- a/abstractrunner.cpp +++ b/abstractrunner.cpp @@ -125,6 +125,10 @@ void AbstractRunner::performMatch(Plasma::RunnerContext &localContext) static const int reasonableRunTime = 1500; static const int fastEnoughTime = 250; + if (d->suspendMatching) { + return; + } + QTime time; time.restart(); @@ -360,6 +364,21 @@ DataEngine *AbstractRunner::dataEngine(const QString &name) const return d->dataEngine(name); } +bool AbstractRunner::isMatchingSuspended() const +{ + return d->suspendMatching; +} + +void AbstractRunner::suspendMatching(bool suspend) +{ + if (d->suspendMatching == suspend) { + return; + } + + d->suspendMatching = suspend; + emit matchingSuspended(suspend); +} + AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r) : priority(AbstractRunner::NormalPriority), speed(AbstractRunner::NormalSpeed), @@ -368,8 +387,9 @@ AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r) runner(r), fastRuns(0), package(0), + defaultSyntax(0), hasRunOptions(false), - defaultSyntax(0) + suspendMatching(false) { } diff --git a/abstractrunner.h b/abstractrunner.h index 1bf19326f..aabc80522 100644 --- a/abstractrunner.h +++ b/abstractrunner.h @@ -63,6 +63,7 @@ class AbstractRunnerPrivate; class PLASMA_EXPORT AbstractRunner : public QObject { Q_OBJECT + Q_PROPERTY(bool matchingSuspended READ isMatchingSuspended WRITE suspendMatching NOTIFY matchingSuspended) public: /** Specifies a nominal speed for the runner */ @@ -257,6 +258,13 @@ class PLASMA_EXPORT AbstractRunner : public QObject */ RunnerSyntax *defaultSyntax() const; + /** + * @return true if the runner is currently busy with non-interuptable work, signaling that + * new threads should not be created for it at this time + * @since 4.6 + */ + bool isMatchingSuspended() const; + Q_SIGNALS: /** * This signal is emitted when matching is about to commence, giving runners @@ -277,6 +285,13 @@ class PLASMA_EXPORT AbstractRunner : public QObject */ void teardown(); + /** + * Emitted when the runner enters or exits match suspension + * @see matchingSuspended + * @since 4.6 + */ + void matchingSuspended(bool suspended); + protected: friend class RunnerManager; friend class RunnerManagerPrivate; @@ -286,6 +301,12 @@ class PLASMA_EXPORT AbstractRunner : public QObject AbstractRunner(QObject *parent, const QVariantList &args); + /** + * Sets whether or not the runner is available for match requests. Useful to + * prevent more thread spawning when the thread is in a busy state. + */ + void suspendMatching(bool suspend); + /** * Provides access to the runner's configuration object. */ diff --git a/private/abstractrunner_p.h b/private/abstractrunner_p.h index fc8af8885..2ec800b09 100644 --- a/private/abstractrunner_p.h +++ b/private/abstractrunner_p.h @@ -46,12 +46,13 @@ public: KPluginInfo runnerDescription; AbstractRunner *runner; int fastRuns; + QReadWriteLock speedLock; Package *package; QHash actions; QList syntaxes; - bool hasRunOptions; - QReadWriteLock speedLock; RunnerSyntax *defaultSyntax; + bool hasRunOptions : 1; + bool suspendMatching : 1; }; } // namespace Plasma diff --git a/runnermanager.cpp b/runnermanager.cpp index 79c2de3e0..7c24fee8b 100644 --- a/runnermanager.cpp +++ b/runnermanager.cpp @@ -263,6 +263,7 @@ public: if (runner) { kDebug() << "================= loading runner:" << service->name() << "================="; + QObject::connect(runner, SIGNAL(matchingSuspended(bool)), q, SLOT(runnerMatchingSuspended(bool))); QMetaObject::invokeMethod(runner, "init"); } @@ -352,6 +353,32 @@ public: QObject::connect(dummy, SIGNAL(done(ThreadWeaver::Job*)), dummy, SLOT(deleteLater())); } + void runnerMatchingSuspended(bool suspended) + { + if (suspended || !prepped || teardownRequested) { + return; + } + + AbstractRunner *runner = qobject_cast(q->sender()); + + if (runner) { + startJob(runner); + } + } + + void startJob(AbstractRunner *runner) + { + if ((runner->ignoredTypes() & context.type()) == 0) { + FindMatchesJob *job = new FindMatchesJob(runner, &context, Weaver::instance()); + QObject::connect(job, SIGNAL(done(ThreadWeaver::Job*)), q, SLOT(jobDone(ThreadWeaver::Job*))); + if (runner->speed() == AbstractRunner::SlowSpeed) { + job->setDelayTimer(&delayTimer); + } + Weaver::instance()->enqueue(job); + searchJobs.insert(job); + } + } + // Delay in ms before slow runners are allowed to run static const int slowRunDelay = 400; @@ -445,6 +472,7 @@ void RunnerManager::loadRunner(const QString &path) { if (!d->runners.contains(path)) { AbstractRunner *runner = new AbstractRunner(this, path); + connect(runner, SIGNAL(matchingSuspended(bool)), this, SLOT(runnerMatchingSuspended(bool))); d->runners.insert(path, runner); } } @@ -580,12 +608,12 @@ QMimeData * RunnerManager::mimeDataForMatch(const QString &id) const QMimeData * RunnerManager::mimeDataForMatch(const QueryMatch &match) const { AbstractRunner *runner = match.runner(); - QMimeData * mimeData; + QMimeData *mimeData; if (runner && QMetaObject::invokeMethod( runner, "mimeDataForMatch", Qt::DirectConnection, Q_RETURN_ARG(QMimeData*, mimeData), - Q_ARG(const Plasma::QueryMatch *, & match) + Q_ARG(const Plasma::QueryMatch *, &match) )) { return mimeData; } @@ -689,16 +717,11 @@ void RunnerManager::launchQuery(const QString &untrimmedTerm, const QString &run } foreach (Plasma::AbstractRunner *r, runable) { - if ((r->ignoredTypes() & d->context.type()) == 0) { -// kDebug() << "launching" << r->name(); - FindMatchesJob *job = new FindMatchesJob(r, &d->context, Weaver::instance()); - connect(job, SIGNAL(done(ThreadWeaver::Job*)), this, SLOT(jobDone(ThreadWeaver::Job*))); - if (r->speed() == AbstractRunner::SlowSpeed) { - job->setDelayTimer(&d->delayTimer); - } - Weaver::instance()->enqueue(job); - d->searchJobs.insert(job); + if (r->isMatchingSuspended()) { + continue; } + + d->startJob(r); } // Start timer to unblock slow runners diff --git a/runnermanager.h b/runnermanager.h index 64f04579c..341d22fe5 100644 --- a/runnermanager.h +++ b/runnermanager.h @@ -290,6 +290,7 @@ class PLASMA_EXPORT RunnerManager : public QObject Q_PRIVATE_SLOT(d, void matchesChanged()) Q_PRIVATE_SLOT(d, void jobDone(ThreadWeaver::Job*)) Q_PRIVATE_SLOT(d, void unblockJobs()) + Q_PRIVATE_SLOT(d, void runnerMatchingSuspended(bool)) RunnerManagerPrivate * const d;