diff options
| author | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-07-22 13:58:42 +0200 |
|---|---|---|
| committer | Christian Kandeler <christian.kandeler@digia.com> | 2013-07-22 17:51:53 +0200 |
| commit | ce7d8494dcac8b763fa0045e8cb7183a01293d5f (patch) | |
| tree | b3550cd581c3486215d804760baae36232546c51 /src/lib/api | |
| parent | dc78a3c1e56b086d1ce050ab81b4595a1cf90f04 (diff) | |
| download | qbs-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>
Diffstat (limited to 'src/lib/api')
| -rw-r--r-- | src/lib/api/internaljobs.cpp | 138 | ||||
| -rw-r--r-- | src/lib/api/internaljobs.h | 61 | ||||
| -rw-r--r-- | src/lib/api/jobs.cpp | 32 |
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 ¶meters) +void InternalSetupProjectJob::init(const SetupProjectParameters ¶meters) { 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 ¶meters); + void init(const SetupProjectParameters ¶meters); 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 ¶meters) { - 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 |
