Add gui thread mode to BuildStep

Change-Id: I11501635bc5c17db557ea8379eb63c9d3915a05e
Reviewed-on: http://codereview.qt.nokia.com/1316
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Christian Kandeler <christian.kandeler@nokia.com>
This commit is contained in:
Daniel Teske
2011-07-07 15:15:43 +02:00
parent f3a45d7b55
commit 69cca88dbb
4 changed files with 75 additions and 4 deletions

View File

@@ -84,6 +84,7 @@ struct BuildManagerPrivate {
ProjectExplorerPlugin *m_projectExplorerPlugin;
bool m_running;
QFutureWatcher<bool> m_watcher;
QFutureInterface<bool> m_futureInterfaceForAysnc;
BuildStep *m_currentBuildStep;
QString m_currentConfiguration;
// used to decide if we are building a project to decide when to emit buildStateChanged(Project *)
@@ -91,6 +92,8 @@ struct BuildManagerPrivate {
Project *m_previousBuildStepProject;
// is set to true while canceling, so that nextBuildStep knows that the BuildStep finished because of canceling
bool m_canceling;
bool m_doNotEnterEventLoop;
QEventLoop *m_eventLoop;
// Progress reporting to the progress manager
int m_progress;
@@ -103,6 +106,8 @@ BuildManagerPrivate::BuildManagerPrivate() :
m_running(false)
, m_previousBuildStepProject(0)
, m_canceling(false)
, m_doNotEnterEventLoop(false)
, m_eventLoop(0)
, m_maxProgress(0)
, m_progressFutureInterface(0)
{
@@ -190,7 +195,20 @@ void BuildManager::cancel()
if (d->m_running) {
d->m_canceling = true;
d->m_watcher.cancel();
d->m_watcher.waitForFinished();
if (d->m_currentBuildStep->runInGuiThread()) {
// This is evil. A nested event loop.
d->m_currentBuildStep->cancel();
if (d->m_doNotEnterEventLoop) {
d->m_doNotEnterEventLoop = false;
} else {
d->m_eventLoop = new QEventLoop;
d->m_eventLoop->exec();
delete d->m_eventLoop;
d->m_eventLoop = 0;
}
} else {
d->m_watcher.waitForFinished();
}
// The cancel message is added to the output window via a single shot timer
// since the canceling is likely to have generated new addToOutputWindow signals
@@ -332,6 +350,21 @@ void BuildManager::addToOutputWindow(const QString &string, BuildStep::OutputFor
d->m_outputWindow->appendText(stringToWrite, format);
}
void BuildManager::buildStepFinishedAsync()
{
disconnect(d->m_currentBuildStep, SIGNAL(finished()),
this, SLOT(buildStepFinishedAsync()));
d->m_futureInterfaceForAysnc = QFutureInterface<bool>();
if (d->m_canceling) {
if (d->m_eventLoop)
d->m_eventLoop->exit();
else
d->m_doNotEnterEventLoop = true;
} else {
nextBuildQueue();
}
}
void BuildManager::nextBuildQueue()
{
if (d->m_canceling)
@@ -393,7 +426,14 @@ void BuildManager::nextStep()
.arg(projectName), BuildStep::MessageOutput);
d->m_previousBuildStepProject = d->m_currentBuildStep->buildConfiguration()->target()->project();
}
d->m_watcher.setFuture(QtConcurrent::run(&BuildStep::run, d->m_currentBuildStep));
if (d->m_currentBuildStep->runInGuiThread()) {
connect (d->m_currentBuildStep, SIGNAL(finished()),
this, SLOT(buildStepFinishedAsync()));
d->m_watcher.setFuture(d->m_futureInterfaceForAysnc.future());
d->m_currentBuildStep->run(d->m_futureInterfaceForAysnc);
} else {
d->m_watcher.setFuture(QtConcurrent::run(&BuildStep::run, d->m_currentBuildStep));
}
} else {
d->m_running = false;
d->m_previousBuildStepProject = 0;

View File

@@ -87,6 +87,7 @@ private slots:
void addToOutputWindow(const QString &string, ProjectExplorer::BuildStep::OutputFormat,
ProjectExplorer::BuildStep::OutputNewlineSetting = BuildStep::DoAppendNewline);
void buildStepFinishedAsync();
void nextBuildQueue();
void progressChanged();
void progressTextChanged();

View File

@@ -69,13 +69,18 @@
\fn void ProjectExplorer::BuildStep::run(QFutureInterface<bool> &fi)
Reimplement this. This function is called when the target is build.
This function is NOT run in the gui thread. It runs in its own thread
If you need an event loop, you need to create one.
By default this function is NOT run in the gui thread. It runs in its
own thread. If you need an event loop, you need to create one.
This function should block until the task is done
The absolute minimal implementation is:
\code
fi.reportResult(true);
\endcode
By returning true from \sa runInGuiThread() this function is called in the
gui thread. Then the function should not block and instead the
finished() signal should be emitted.
*/
/*!
@@ -106,6 +111,17 @@
It should be in plain text, with the format in the parameter.
*/
/*!
\fn void ProjectExplorer::BuildStep::cancel() const
This function needs to be reimplemented only for BuildSteps that return false from \sa runInGuiThread.
*/
/*!
\fn void ProjectExplorer::BuildStep::finished()
\brief This signal needs to be emitted if the BuildStep runs in the gui thread.
*/
using namespace ProjectExplorer;
BuildStep::BuildStep(BuildStepList *bsl, const QString &id) :
@@ -150,6 +166,16 @@ bool BuildStep::immutable() const
return false;
}
bool BuildStep::runInGuiThread() const
{
return false;
}
void BuildStep::cancel()
{
// Do nothing
}
IBuildStepFactory::IBuildStepFactory(QObject *parent) :
QObject(parent)
{ }

View File

@@ -68,6 +68,8 @@ public:
virtual BuildStepConfigWidget *createConfigWidget() = 0;
virtual bool immutable() const;
virtual bool runInGuiThread() const;
virtual void cancel();
BuildConfiguration *buildConfiguration() const;
DeployConfiguration *deployConfiguration() const;
@@ -81,6 +83,8 @@ signals:
void addOutput(const QString &string, ProjectExplorer::BuildStep::OutputFormat format,
ProjectExplorer::BuildStep::OutputNewlineSetting newlineSetting = DoAppendNewline) const;
void finished();
};
class PROJECTEXPLORER_EXPORT IBuildStepFactory :