ProjectExplorer: Add stop dependencies for RunWorkers

A run worker will only be stopped if all its stop dependencies are
stopped.

Change-Id: I16a42253874adafb9ca87d175bfb361fae46cc39
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Ulf Hermann
2017-08-08 14:49:49 +02:00
parent 8b5582c424
commit a028f6717f
2 changed files with 67 additions and 68 deletions

View File

@@ -532,12 +532,14 @@ public:
RunWorkerPrivate(RunWorker *runWorker, RunControl *runControl); RunWorkerPrivate(RunWorker *runWorker, RunControl *runControl);
bool canStart() const; bool canStart() const;
bool canStop() const;
void timerEvent(QTimerEvent *ev) override; void timerEvent(QTimerEvent *ev) override;
RunWorker *q; RunWorker *q;
RunWorkerState state = RunWorkerState::Initialized; RunWorkerState state = RunWorkerState::Initialized;
QPointer<RunControl> runControl; QPointer<RunControl> runControl;
QList<RunWorker *> startDependencies; QList<RunWorker *> startDependencies;
QList<RunWorker *> stopDependencies;
QString id; QString id;
QVariantMap data; QVariantMap data;
@@ -612,6 +614,7 @@ public:
void initiateReStart(); void initiateReStart();
void continueStart(); void continueStart();
void initiateStop(); void initiateStop();
void continueStopOrFinish();
void initiateFinish(); void initiateFinish();
void onWorkerStarted(RunWorker *worker); void onWorkerStarted(RunWorker *worker);
@@ -833,7 +836,23 @@ void RunControlPrivate::initiateStop()
setState(RunControlState::Stopping); setState(RunControlState::Stopping);
debugMessage("Queue: Stopping for all workers"); debugMessage("Queue: Stopping for all workers");
continueStopOrFinish();
}
void RunControlPrivate::continueStopOrFinish()
{
bool allDone = true; bool allDone = true;
auto queueStop = [this](RunWorker *worker, const QString &message) {
if (worker->d->canStop()) {
debugMessage(message);
worker->d->state = RunWorkerState::Stopping;
QTimer::singleShot(0, worker, &RunWorker::initiateStop);
} else {
debugMessage(" " + worker->d->id + " is waiting for dependent workers to stop");
}
};
for (RunWorker *worker : m_workers) { for (RunWorker *worker : m_workers) {
if (worker) { if (worker) {
const QString &workerId = worker->d->id; const QString &workerId = worker->d->id;
@@ -848,16 +867,12 @@ void RunControlPrivate::initiateStop()
allDone = false; allDone = false;
break; break;
case RunWorkerState::Starting: case RunWorkerState::Starting:
debugMessage(" " + workerId + " was Starting, queuing stop"); queueStop(worker, " " + workerId + " was Starting, queuing stop");
worker->d->state = RunWorkerState::Stopping;
QTimer::singleShot(0, worker, &RunWorker::initiateStop);
allDone = false; allDone = false;
break; break;
case RunWorkerState::Running: case RunWorkerState::Running:
debugMessage(" " + workerId + " was Running, queuing stop"); queueStop(worker, " " + workerId + " was Running, queuing stop");
worker->d->state = RunWorkerState::Stopping;
allDone = false; allDone = false;
QTimer::singleShot(0, worker, &RunWorker::initiateStop);
break; break;
case RunWorkerState::Done: case RunWorkerState::Done:
debugMessage(" " + workerId + " was Done. Good."); debugMessage(" " + workerId + " was Done. Good.");
@@ -870,11 +885,20 @@ void RunControlPrivate::initiateStop()
debugMessage("Found unknown deleted worker"); debugMessage("Found unknown deleted worker");
} }
} }
if (allDone) {
debugMessage("All stopped."); RunControlState targetState;
setState(RunControlState::Stopped); if (state == RunControlState::Finishing) {
targetState = RunControlState::Finished;
} else { } else {
debugMessage("Not all workers stopped. Waiting..."); checkState(RunControlState::Stopping);
targetState = RunControlState::Stopped;
}
if (allDone) {
debugMessage("All Stopped");
setState(targetState);
} else {
debugMessage("Not all workers Stopped. Waiting...");
} }
} }
@@ -883,48 +907,7 @@ void RunControlPrivate::initiateFinish()
setState(RunControlState::Finishing); setState(RunControlState::Finishing);
debugMessage("Ramping down"); debugMessage("Ramping down");
bool allDone = true; continueStopOrFinish();
for (RunWorker *worker : m_workers) {
if (worker) {
const QString &workerId = worker->d->id;
debugMessage(" Examining worker " + workerId);
switch (worker->d->state) {
case RunWorkerState::Initialized:
debugMessage(" " + workerId + " was Initialized, setting to Done");
worker->d->state = RunWorkerState::Done;
break;
case RunWorkerState::Stopping:
debugMessage(" " + workerId + " was already Stopping. Keeping it that way");
allDone = false;
break;
case RunWorkerState::Starting:
debugMessage(" " + workerId + " was Starting, queuing stop");
worker->d->state = RunWorkerState::Stopping;
QTimer::singleShot(0, worker, &RunWorker::initiateStop);
allDone = false;
break;
case RunWorkerState::Running:
debugMessage(" " + workerId + " was Running, queuing stop");
worker->d->state = RunWorkerState::Stopping;
allDone = false;
QTimer::singleShot(0, worker, &RunWorker::initiateStop);
break;
case RunWorkerState::Done:
debugMessage(" " + workerId + " was Done. Good.");
break;
case RunWorkerState::Failed:
debugMessage(" " + workerId + " was Failed. Good");
break;
}
} else {
debugMessage("Found unknown deleted worker");
}
}
if (allDone) {
setState(RunControlState::Finished);
} else {
debugMessage("Not all workers finished. Waiting...");
}
} }
void RunControlPrivate::onWorkerStarted(RunWorker *worker) void RunControlPrivate::onWorkerStarted(RunWorker *worker)
@@ -973,6 +956,11 @@ void RunControlPrivate::onWorkerStopped(RunWorker *worker)
break; break;
} }
if (state == RunControlState::Finishing || state == RunControlState::Stopping) {
continueStopOrFinish();
return;
}
debugMessage("Checking whether all stopped"); debugMessage("Checking whether all stopped");
bool allDone = true; bool allDone = true;
for (RunWorker *worker : m_workers) { for (RunWorker *worker : m_workers) {
@@ -1006,14 +994,7 @@ void RunControlPrivate::onWorkerStopped(RunWorker *worker)
debugMessage("Found unknown deleted worker"); debugMessage("Found unknown deleted worker");
} }
} }
if (state == RunControlState::Finishing) {
if (allDone) {
debugMessage("All finished. Deleting myself");
setState(RunControlState::Finished);
} else {
debugMessage("Not all workers finished. Waiting...");
}
} else {
if (allDone) { if (allDone) {
if (state == RunControlState::Stopped) { if (state == RunControlState::Stopped) {
debugMessage("All workers stopped, but runControl was already stopped."); debugMessage("All workers stopped, but runControl was already stopped.");
@@ -1025,7 +1006,6 @@ void RunControlPrivate::onWorkerStopped(RunWorker *worker)
debugMessage("Not all workers stopped. Waiting..."); debugMessage("Not all workers stopped. Waiting...");
} }
} }
}
void RunControlPrivate::showError(const QString &msg) void RunControlPrivate::showError(const QString &msg)
{ {
@@ -1456,7 +1436,7 @@ bool RunWorkerPrivate::canStart() const
if (state != RunWorkerState::Initialized) if (state != RunWorkerState::Initialized)
return false; return false;
for (RunWorker *worker : startDependencies) { for (RunWorker *worker : startDependencies) {
QTC_ASSERT(worker, return true); QTC_ASSERT(worker, continue);
if (worker->d->state != RunWorkerState::Done if (worker->d->state != RunWorkerState::Done
&& worker->d->state != RunWorkerState::Running) && worker->d->state != RunWorkerState::Running)
return false; return false;
@@ -1464,6 +1444,19 @@ bool RunWorkerPrivate::canStart() const
return true; return true;
} }
bool RunWorkerPrivate::canStop() const
{
if (state != RunWorkerState::Starting && state != RunWorkerState::Running)
return false;
for (RunWorker *worker : stopDependencies) {
QTC_ASSERT(worker, continue);
if (worker->d->state != RunWorkerState::Done
&& worker->d->state != RunWorkerState::Failed)
return false;
}
return true;
}
void RunWorkerPrivate::timerEvent(QTimerEvent *ev) void RunWorkerPrivate::timerEvent(QTimerEvent *ev)
{ {
if (ev->timerId() == startWatchdogTimerId) { if (ev->timerId() == startWatchdogTimerId) {
@@ -1623,6 +1616,11 @@ void RunWorker::addStartDependency(RunWorker *dependency)
d->startDependencies.append(dependency); d->startDependencies.append(dependency);
} }
void RunWorker::addStopDependency(RunWorker *dependency)
{
d->stopDependencies.append(dependency);
}
RunControl *RunWorker::runControl() const RunControl *RunWorker::runControl() const
{ {
return d->runControl; return d->runControl;

View File

@@ -323,6 +323,7 @@ public:
RunControl *runControl() const; RunControl *runControl() const;
void addStartDependency(RunWorker *dependency); void addStartDependency(RunWorker *dependency);
void addStopDependency(RunWorker *dependency);
void setDisplayName(const QString &id) { setId(id); } // FIXME: Obsoleted by setId. void setDisplayName(const QString &id) { setId(id); } // FIXME: Obsoleted by setId.
void setId(const QString &id); void setId(const QString &id);