summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@digia.com>2013-07-22 13:58:42 +0200
committerChristian Kandeler <christian.kandeler@digia.com>2013-07-22 17:51:53 +0200
commitce7d8494dcac8b763fa0045e8cb7183a01293d5f (patch)
treeb3550cd581c3486215d804760baae36232546c51
parentdc78a3c1e56b086d1ce050ab81b4595a1cf90f04 (diff)
downloadqbs-ce7d8494dcac8b763fa0045e8cb7183a01293d5f.tar.gz
remove QtConcurrent dependency from internal job classes
For rationale see dc78a3c1. Task-number: QBS-307 Change-Id: Ia9dcfd52e9c71964c0bd788dffc98dfbdd0aef91 Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
-rw-r--r--src/lib/api/internaljobs.cpp138
-rw-r--r--src/lib/api/internaljobs.h61
-rw-r--r--src/lib/api/jobs.cpp32
3 files changed, 137 insertions, 94 deletions
diff --git a/src/lib/api/internaljobs.cpp b/src/lib/api/internaljobs.cpp
index 0510a87e4..875f2d0d5 100644
--- a/src/lib/api/internaljobs.cpp
+++ b/src/lib/api/internaljobs.cpp
@@ -46,11 +46,8 @@
#include <tools/preferences.h>
#include <tools/qbsassert.h>
-#include <QtConcurrentRun>
-#include <QFutureWatcher>
-#include <QMutexLocker>
+#include <QEventLoop>
#include <QScopedPointer>
-#include <QThread>
#include <QTimer>
namespace qbs {
@@ -109,16 +106,32 @@ private:
InternalJob::InternalJob(const Logger &logger, QObject *parent)
: QObject(parent)
, m_observer(new JobObserver(this))
+ , m_ownsObserver(true)
, m_logger(logger)
, m_timed(false)
{
}
+InternalJob::~InternalJob()
+{
+ if (m_ownsObserver)
+ delete m_observer;
+}
+
void InternalJob::cancel()
{
m_observer->cancel();
}
+void InternalJob::shareObserverWith(InternalJob *otherJob)
+{
+ if (m_ownsObserver) {
+ delete m_observer;
+ m_ownsObserver = false;
+ }
+ m_observer = otherJob->m_observer;
+}
+
void InternalJob::storeBuildGraph(const TopLevelProjectConstPtr &project)
{
try {
@@ -128,30 +141,74 @@ void InternalJob::storeBuildGraph(const TopLevelProjectConstPtr &project)
}
}
-InternalSetupProjectJob::InternalSetupProjectJob(const Logger &logger, QObject *parent)
- : InternalJob(logger, parent), m_running(false)
+
+/**
+ * Construct a new thread wrapper for a synchronous job.
+ * This object takes over ownership of the synchronous job.
+ */
+InternalJobThreadWrapper::InternalJobThreadWrapper(InternalJob *synchronousJob, QObject *parent)
+ : InternalJob(synchronousJob->logger(), parent)
+ , m_job(synchronousJob)
+ , m_running(false)
+{
+ synchronousJob->shareObserverWith(this);
+ m_job->moveToThread(&m_thread);
+ connect(m_job, SIGNAL(finished(Internal::InternalJob*)), SLOT(handleFinished()));
+ connect(m_job, SIGNAL(newTaskStarted(QString,int,Internal::InternalJob*)),
+ SIGNAL(newTaskStarted(QString,int,Internal::InternalJob*)));
+ connect(m_job, SIGNAL(taskProgress(int,Internal::InternalJob*)),
+ SIGNAL(taskProgress(int,Internal::InternalJob*)));
+ connect(m_job, SIGNAL(totalEffortChanged(int,Internal::InternalJob*)),
+ SIGNAL(totalEffortChanged(int,Internal::InternalJob*)));
+ m_job->connect(this, SIGNAL(startRequested()), SLOT(start()));
+}
+
+InternalJobThreadWrapper::~InternalJobThreadWrapper()
+{
+ if (m_running) {
+ QEventLoop loop;
+ loop.connect(m_job, SIGNAL(finished(Internal::InternalJob*)), SLOT(quit));
+ loop.exec();
+ }
+ m_thread.quit();
+ m_thread.wait();
+ delete m_job;
+}
+
+void InternalJobThreadWrapper::start()
+{
+ m_thread.start();
+ m_running = true;
+ emit startRequested();
+}
+
+void InternalJobThreadWrapper::handleFinished()
+{
+ m_running = false;
+ setError(m_job->error());
+ emit finished(this);
+}
+
+
+InternalSetupProjectJob::InternalSetupProjectJob(const Logger &logger)
+ : InternalJob(logger)
{
}
InternalSetupProjectJob::~InternalSetupProjectJob()
{
- QMutexLocker locker(&m_runMutex);
- while (m_running)
- m_runWaitCondition.wait(&m_runMutex);
- }
+}
-void InternalSetupProjectJob::resolve(const SetupProjectParameters &parameters)
+void InternalSetupProjectJob::init(const SetupProjectParameters &parameters)
{
m_parameters = parameters;
setTimed(parameters.logElapsedTime());
- QTimer::singleShot(0, this, SLOT(start()));
}
void InternalSetupProjectJob::reportError(const ErrorInfo &error)
{
setError(error);
- QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection,
- Q_ARG(Internal::InternalJob *, this));
+ emit finished(this);
}
TopLevelProjectPtr InternalSetupProjectJob::project() const
@@ -161,27 +218,12 @@ TopLevelProjectPtr InternalSetupProjectJob::project() const
void InternalSetupProjectJob::start()
{
- m_running = true;
- QFutureWatcher<void> * const watcher = new QFutureWatcher<void>(this);
- connect(watcher, SIGNAL(finished()), SLOT(handleFinished()));
- watcher->setFuture(QtConcurrent::run(this, &InternalSetupProjectJob::doResolve));
-}
-
-void InternalSetupProjectJob::handleFinished()
-{
- emit finished(this);
-}
-
-void InternalSetupProjectJob::doResolve()
-{
try {
execute();
} catch (const ErrorInfo &error) {
setError(error);
}
- QMutexLocker locker(&m_runMutex);
- m_running = false;
- m_runWaitCondition.wakeOne();
+ emit finished(this);
}
void InternalSetupProjectJob::execute()
@@ -322,29 +364,16 @@ InternalCleanJob::InternalCleanJob(const Logger &logger, QObject *parent)
{
}
-void InternalCleanJob::clean(const TopLevelProjectPtr &project,
+void InternalCleanJob::init(const TopLevelProjectPtr &project,
const QList<ResolvedProductPtr> &products, const CleanOptions &options)
{
setup(project, products, options.dryRun());
setTimed(options.logElapsedTime());
m_options = options;
- QTimer::singleShot(0, this, SLOT(start()));
}
void InternalCleanJob::start()
{
- QFutureWatcher<void> * const watcher = new QFutureWatcher<void>(this);
- connect(watcher, SIGNAL(finished()), SLOT(handleFinished()));
- watcher->setFuture(QtConcurrent::run(this, &InternalCleanJob::doClean));
-}
-
-void InternalCleanJob::handleFinished()
-{
- emit finished(this);
-}
-
-void InternalCleanJob::doClean()
-{
try {
ArtifactCleaner cleaner(logger(), observer());
cleaner.cleanup(project(), products(), m_options);
@@ -352,11 +381,12 @@ void InternalCleanJob::doClean()
setError(error);
}
storeBuildGraph();
+ emit finished(this);
}
-InternalInstallJob::InternalInstallJob(const Logger &logger, QObject *parent)
- : InternalJob(logger, parent)
+InternalInstallJob::InternalInstallJob(const Logger &logger)
+ : InternalJob(logger)
{
}
@@ -364,35 +394,23 @@ InternalInstallJob::~InternalInstallJob()
{
}
-void InternalInstallJob::install(const TopLevelProjectPtr &project,
+void InternalInstallJob::init(const TopLevelProjectPtr &project,
const QList<ResolvedProductPtr> &products, const InstallOptions &options)
{
m_project = project;
m_products = products;
m_options = options;
setTimed(options.logElapsedTime());
- QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
-}
-
-void InternalInstallJob::handleFinished()
-{
- emit finished(this);
}
void InternalInstallJob::start()
{
- QFutureWatcher<void> * const watcher = new QFutureWatcher<void>(this);
- connect(watcher, SIGNAL(finished()), SLOT(handleFinished()));
- watcher->setFuture(QtConcurrent::run(this, &InternalInstallJob::doInstall));
-}
-
-void InternalInstallJob::doInstall()
-{
try {
ProductInstaller(m_project, m_products, m_options, observer(), logger()).install();
} catch (const ErrorInfo &error) {
setError(error);
}
+ emit finished(this);
}
} // namespace Internal
diff --git a/src/lib/api/internaljobs.h b/src/lib/api/internaljobs.h
index 0c1855082..08a451a40 100644
--- a/src/lib/api/internaljobs.h
+++ b/src/lib/api/internaljobs.h
@@ -39,9 +39,8 @@
#include <tools/setupprojectparameters.h>
#include <QList>
-#include <QMutex>
#include <QObject>
-#include <QWaitCondition>
+#include <QThread>
namespace qbs {
class ProcessResult;
@@ -58,11 +57,14 @@ class InternalJob : public QObject
Q_OBJECT
friend class JobObserver;
public:
+ ~InternalJob();
+
void cancel();
ErrorInfo error() const { return m_error; }
Logger logger() const { return m_logger; }
bool timed() const { return m_timed; }
+ void shareObserverWith(InternalJob *otherJob);
protected:
explicit InternalJob(const Logger &logger, QObject *parent = 0);
@@ -80,40 +82,57 @@ signals:
private:
ErrorInfo m_error;
- JobObserver * const m_observer;
+ JobObserver *m_observer;
+ bool m_ownsObserver;
Logger m_logger;
bool m_timed;
};
+class InternalJobThreadWrapper : public InternalJob
+{
+ Q_OBJECT
+public:
+ InternalJobThreadWrapper(InternalJob *synchronousJob, QObject *parent = 0);
+ ~InternalJobThreadWrapper();
+
+ void start();
+ InternalJob *synchronousJob() const { return m_job; }
+
+signals:
+ void startRequested();
+
+private slots:
+ void handleFinished();
+
+private:
+ QThread m_thread;
+ InternalJob *m_job;
+ bool m_running;
+};
+
class InternalSetupProjectJob : public InternalJob
{
Q_OBJECT
public:
- InternalSetupProjectJob(const Logger &logger, QObject *parent = 0);
+ InternalSetupProjectJob(const Logger &logger);
~InternalSetupProjectJob();
- void resolve(const SetupProjectParameters &parameters);
+ void init(const SetupProjectParameters &parameters);
void reportError(const ErrorInfo &error);
TopLevelProjectPtr project() const;
private slots:
void start();
- void handleFinished();
private:
void resolveProjectFromScratch(Internal::ScriptEngine *engine);
void resolveBuildDataFromScratch(const RulesEvaluationContextPtr &evalContext);
void setupPlatformEnvironment();
BuildGraphLoadResult restoreProject(const RulesEvaluationContextPtr &evalContext);
- void doResolve();
void execute();
- bool m_running;
- QMutex m_runMutex;
- QWaitCondition m_runWaitCondition;
-
TopLevelProjectPtr m_project;
SetupProjectParameters m_parameters;
};
@@ -169,37 +188,29 @@ class InternalCleanJob : public BuildGraphTouchingJob
public:
InternalCleanJob(const Logger &logger, QObject *parent = 0);
- void clean(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
- const CleanOptions &options);
+ void init(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
+ const CleanOptions &options);
private slots:
void start();
- void handleFinished();
private:
- void doClean();
-
CleanOptions m_options;
};
-// TODO: Common base class for all jobs that need to start a thread?
class InternalInstallJob : public InternalJob
{
Q_OBJECT
public:
- InternalInstallJob(const Logger &logger, QObject *parent = 0);
+ InternalInstallJob(const Logger &logger);
~InternalInstallJob();
- void install(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
- const InstallOptions &options);
+ void init(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
+ const InstallOptions &options);
private slots:
- void handleFinished();
-
-private:
- Q_INVOKABLE void start();
- void doInstall();
+ void start();
private:
TopLevelProjectPtr m_project;
diff --git a/src/lib/api/jobs.cpp b/src/lib/api/jobs.cpp
index c139ee215..068a991e8 100644
--- a/src/lib/api/jobs.cpp
+++ b/src/lib/api/jobs.cpp
@@ -176,7 +176,7 @@ void AbstractJob::handleFinished()
*/
SetupProjectJob::SetupProjectJob(const Logger &logger, QObject *parent)
- : AbstractJob(new InternalSetupProjectJob(logger), parent)
+ : AbstractJob(new InternalJobThreadWrapper(new InternalSetupProjectJob(logger)), parent)
{
}
@@ -187,20 +187,29 @@ SetupProjectJob::SetupProjectJob(const Logger &logger, QObject *parent)
*/
Project SetupProjectJob::project() const
{
+ const InternalJobThreadWrapper * const wrapper
+ = qobject_cast<InternalJobThreadWrapper *>(internalJob());
const InternalSetupProjectJob * const job
- = qobject_cast<InternalSetupProjectJob *>(internalJob());
+ = qobject_cast<InternalSetupProjectJob *>(wrapper->synchronousJob());
return Project(job->project(), job->logger());
}
void SetupProjectJob::resolve(const SetupProjectParameters &parameters)
{
- InternalSetupProjectJob * const job = qobject_cast<InternalSetupProjectJob *>(internalJob());
- job->resolve(parameters);
+ InternalJobThreadWrapper * const wrapper
+ = qobject_cast<InternalJobThreadWrapper *>(internalJob());
+ InternalSetupProjectJob * const job
+ = qobject_cast<InternalSetupProjectJob *>(wrapper->synchronousJob());
+ job->init(parameters);
+ wrapper->start();
}
void SetupProjectJob::reportError(const ErrorInfo &error)
{
- InternalSetupProjectJob * const job = qobject_cast<InternalSetupProjectJob *>(internalJob());
+ InternalJobThreadWrapper * const wrapper
+ = qobject_cast<InternalJobThreadWrapper *>(internalJob());
+ InternalSetupProjectJob * const job
+ = qobject_cast<InternalSetupProjectJob *>(wrapper->synchronousJob());
job->reportError(error);
}
@@ -255,14 +264,16 @@ void BuildJob::build(const TopLevelProjectPtr &project, const QList<ResolvedProd
*/
CleanJob::CleanJob(const Logger &logger, QObject *parent)
- : AbstractJob(new InternalCleanJob(logger), parent)
+ : AbstractJob(new InternalJobThreadWrapper(new InternalCleanJob(logger)), parent)
{
}
void CleanJob::clean(const TopLevelProjectPtr &project, const QList<ResolvedProductPtr> &products,
const qbs::CleanOptions &options)
{
- qobject_cast<InternalCleanJob *>(internalJob())->clean(project, products, options);
+ InternalJobThreadWrapper * wrapper = qobject_cast<InternalJobThreadWrapper *>(internalJob());
+ qobject_cast<InternalCleanJob *>(wrapper->synchronousJob())->init(project, products, options);
+ wrapper->start();
}
/*!
@@ -271,14 +282,17 @@ void CleanJob::clean(const TopLevelProjectPtr &project, const QList<ResolvedProd
*/
InstallJob::InstallJob(const Logger &logger, QObject *parent)
- : AbstractJob(new InternalInstallJob(logger), parent)
+ : AbstractJob(new InternalJobThreadWrapper(new InternalInstallJob(logger)), parent)
{
}
void InstallJob::install(const TopLevelProjectPtr &project,
const QList<ResolvedProductPtr> &products, const InstallOptions &options)
{
- qobject_cast<InternalInstallJob *>(internalJob())->install(project, products, options);
+ InternalJobThreadWrapper *wrapper = qobject_cast<InternalJobThreadWrapper *>(internalJob());
+ InternalInstallJob *installJob = qobject_cast<InternalInstallJob *>(wrapper->synchronousJob());
+ installJob->init(project, products, options);
+ wrapper->start();
}
} // namespace qbs