allow runners to signal that matching should be suspended for them

svn path=/trunk/KDE/kdelibs/; revision=1171157
This commit is contained in:
Aaron J. Seigo 2010-09-02 22:18:03 +00:00
parent 6307f8248f
commit 99b57b9c65
5 changed files with 80 additions and 14 deletions

View File

@ -125,6 +125,10 @@ void AbstractRunner::performMatch(Plasma::RunnerContext &localContext)
static const int reasonableRunTime = 1500; static const int reasonableRunTime = 1500;
static const int fastEnoughTime = 250; static const int fastEnoughTime = 250;
if (d->suspendMatching) {
return;
}
QTime time; QTime time;
time.restart(); time.restart();
@ -360,6 +364,21 @@ DataEngine *AbstractRunner::dataEngine(const QString &name) const
return d->dataEngine(name); 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) AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r)
: priority(AbstractRunner::NormalPriority), : priority(AbstractRunner::NormalPriority),
speed(AbstractRunner::NormalSpeed), speed(AbstractRunner::NormalSpeed),
@ -368,8 +387,9 @@ AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r)
runner(r), runner(r),
fastRuns(0), fastRuns(0),
package(0), package(0),
defaultSyntax(0),
hasRunOptions(false), hasRunOptions(false),
defaultSyntax(0) suspendMatching(false)
{ {
} }

View File

@ -63,6 +63,7 @@ class AbstractRunnerPrivate;
class PLASMA_EXPORT AbstractRunner : public QObject class PLASMA_EXPORT AbstractRunner : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool matchingSuspended READ isMatchingSuspended WRITE suspendMatching NOTIFY matchingSuspended)
public: public:
/** Specifies a nominal speed for the runner */ /** Specifies a nominal speed for the runner */
@ -257,6 +258,13 @@ class PLASMA_EXPORT AbstractRunner : public QObject
*/ */
RunnerSyntax *defaultSyntax() const; 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: Q_SIGNALS:
/** /**
* This signal is emitted when matching is about to commence, giving runners * This signal is emitted when matching is about to commence, giving runners
@ -277,6 +285,13 @@ class PLASMA_EXPORT AbstractRunner : public QObject
*/ */
void teardown(); void teardown();
/**
* Emitted when the runner enters or exits match suspension
* @see matchingSuspended
* @since 4.6
*/
void matchingSuspended(bool suspended);
protected: protected:
friend class RunnerManager; friend class RunnerManager;
friend class RunnerManagerPrivate; friend class RunnerManagerPrivate;
@ -286,6 +301,12 @@ class PLASMA_EXPORT AbstractRunner : public QObject
AbstractRunner(QObject *parent, const QVariantList &args); 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. * Provides access to the runner's configuration object.
*/ */

View File

@ -46,12 +46,13 @@ public:
KPluginInfo runnerDescription; KPluginInfo runnerDescription;
AbstractRunner *runner; AbstractRunner *runner;
int fastRuns; int fastRuns;
QReadWriteLock speedLock;
Package *package; Package *package;
QHash<QString, QAction*> actions; QHash<QString, QAction*> actions;
QList<RunnerSyntax> syntaxes; QList<RunnerSyntax> syntaxes;
bool hasRunOptions;
QReadWriteLock speedLock;
RunnerSyntax *defaultSyntax; RunnerSyntax *defaultSyntax;
bool hasRunOptions : 1;
bool suspendMatching : 1;
}; };
} // namespace Plasma } // namespace Plasma

View File

@ -263,6 +263,7 @@ public:
if (runner) { if (runner) {
kDebug() << "================= loading runner:" << service->name() << "================="; kDebug() << "================= loading runner:" << service->name() << "=================";
QObject::connect(runner, SIGNAL(matchingSuspended(bool)), q, SLOT(runnerMatchingSuspended(bool)));
QMetaObject::invokeMethod(runner, "init"); QMetaObject::invokeMethod(runner, "init");
} }
@ -352,6 +353,32 @@ public:
QObject::connect(dummy, SIGNAL(done(ThreadWeaver::Job*)), dummy, SLOT(deleteLater())); QObject::connect(dummy, SIGNAL(done(ThreadWeaver::Job*)), dummy, SLOT(deleteLater()));
} }
void runnerMatchingSuspended(bool suspended)
{
if (suspended || !prepped || teardownRequested) {
return;
}
AbstractRunner *runner = qobject_cast<AbstractRunner *>(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 // Delay in ms before slow runners are allowed to run
static const int slowRunDelay = 400; static const int slowRunDelay = 400;
@ -445,6 +472,7 @@ void RunnerManager::loadRunner(const QString &path)
{ {
if (!d->runners.contains(path)) { if (!d->runners.contains(path)) {
AbstractRunner *runner = new AbstractRunner(this, path); AbstractRunner *runner = new AbstractRunner(this, path);
connect(runner, SIGNAL(matchingSuspended(bool)), this, SLOT(runnerMatchingSuspended(bool)));
d->runners.insert(path, runner); d->runners.insert(path, runner);
} }
} }
@ -580,12 +608,12 @@ QMimeData * RunnerManager::mimeDataForMatch(const QString &id) const
QMimeData * RunnerManager::mimeDataForMatch(const QueryMatch &match) const QMimeData * RunnerManager::mimeDataForMatch(const QueryMatch &match) const
{ {
AbstractRunner *runner = match.runner(); AbstractRunner *runner = match.runner();
QMimeData * mimeData; QMimeData *mimeData;
if (runner && QMetaObject::invokeMethod( if (runner && QMetaObject::invokeMethod(
runner, runner,
"mimeDataForMatch", Qt::DirectConnection, "mimeDataForMatch", Qt::DirectConnection,
Q_RETURN_ARG(QMimeData*, mimeData), Q_RETURN_ARG(QMimeData*, mimeData),
Q_ARG(const Plasma::QueryMatch *, & match) Q_ARG(const Plasma::QueryMatch *, &match)
)) { )) {
return mimeData; return mimeData;
} }
@ -689,16 +717,11 @@ void RunnerManager::launchQuery(const QString &untrimmedTerm, const QString &run
} }
foreach (Plasma::AbstractRunner *r, runable) { foreach (Plasma::AbstractRunner *r, runable) {
if ((r->ignoredTypes() & d->context.type()) == 0) { if (r->isMatchingSuspended()) {
// kDebug() << "launching" << r->name(); continue;
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);
} }
d->startJob(r);
} }
// Start timer to unblock slow runners // Start timer to unblock slow runners

View File

@ -290,6 +290,7 @@ class PLASMA_EXPORT RunnerManager : public QObject
Q_PRIVATE_SLOT(d, void matchesChanged()) Q_PRIVATE_SLOT(d, void matchesChanged())
Q_PRIVATE_SLOT(d, void jobDone(ThreadWeaver::Job*)) Q_PRIVATE_SLOT(d, void jobDone(ThreadWeaver::Job*))
Q_PRIVATE_SLOT(d, void unblockJobs()) Q_PRIVATE_SLOT(d, void unblockJobs())
Q_PRIVATE_SLOT(d, void runnerMatchingSuspended(bool))
RunnerManagerPrivate * const d; RunnerManagerPrivate * const d;