From d288752fb305f9e6f5bcdaf7c82ca446034f8eed Mon Sep 17 00:00:00 2001 From: heyuming Date: Tue, 18 Jul 2023 15:55:29 +0800 Subject: [PATCH] feat: finish dbus service: job/jobManager Log: --- CMakeLists.txt | 2 +- api/dbus/org.desktopspec.JobManager1.Job.xml | 11 ++-- api/dbus/org.desktopspec.JobManager1.xml | 9 ++-- src/CMakeLists.txt | 1 + src/dbus/jobmanager1service.cpp | 17 ------ src/dbus/jobmanager1service.h | 54 ++++++++++++++++++-- src/dbus/jobservice.cpp | 6 +-- src/dbus/jobservice.h | 11 ++-- src/include/global.h | 2 +- 9 files changed, 72 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 038f1f6..d43ccc9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ set(CMAKE_AUTORCC ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Qt6 REQUIRED COMPONENTS Core DBus) +find_package(Qt6 REQUIRED COMPONENTS Core DBus Concurrent) find_package(Threads REQUIRED) add_subdirectory(src) diff --git a/api/dbus/org.desktopspec.JobManager1.Job.xml b/api/dbus/org.desktopspec.JobManager1.Job.xml index 4848dc1..86facc8 100644 --- a/api/dbus/org.desktopspec.JobManager1.Job.xml +++ b/api/dbus/org.desktopspec.JobManager1.Job.xml @@ -7,7 +7,7 @@ value="Value of `Status` is one of `started`, `running`, `finished`, `suspending`, `suspend`, - `canceled` and `failed`." + `canceled`." /> @@ -22,13 +22,13 @@ will be emitted." /> - + @@ -36,8 +36,7 @@ diff --git a/api/dbus/org.desktopspec.JobManager1.xml b/api/dbus/org.desktopspec.JobManager1.xml index ba365be..8cc0650 100644 --- a/api/dbus/org.desktopspec.JobManager1.xml +++ b/api/dbus/org.desktopspec.JobManager1.xml @@ -26,17 +26,16 @@ - - + -#include "global.h" JobManager1Service::JobManager1Service() = default; JobManager1Service::~JobManager1Service() = default; - -template -void addJob(const QDBusObjectPath &source, F func, Args &&...args) -{ - // TODO: impl -} - -bool JobManager1Service::removeJob(const QDBusObjectPath &job, - const QString &status, - const QString &message, - const QDBusVariant &result) -{ - // TODO: impl - return false; -} diff --git a/src/dbus/jobmanager1service.h b/src/dbus/jobmanager1service.h index eb8f3eb..2c06556 100644 --- a/src/dbus/jobmanager1service.h +++ b/src/dbus/jobmanager1service.h @@ -9,7 +9,14 @@ #include #include #include -#include "jobservice.h" +#include +#include +#include +#include +#include +#include "jobadaptor.h" +#include "global.h" + class JobManager1Service final : public QObject { Q_OBJECT @@ -21,15 +28,52 @@ public: JobManager1Service &operator=(JobManager1Service &&) = delete; ~JobManager1Service() override; - template - void addJob(const QDBusObjectPath &source,F func, Args&& ...args); - bool removeJob(const QDBusObjectPath &job, const QString &status, const QString &message, const QDBusVariant &result); + template + void addJob(const QDBusObjectPath &source, F func, QVariantList args) + { + static_assert(std::is_invocable_v, "param type must be QVariant."); + + QString objectPath{DDEApplicationManager1JobObjectPath + QUuid::createUuid().toString()}; + QFuture future = QtConcurrent::mappedReduced( + args.begin(), args.end(), func, &QVariantList::insert, QVariantList{}, QtConcurrent::ReduceOption::OrderedReduce); + QSharedPointer job{new JobService{future}}; + auto path = QDBusObjectPath{objectPath}; + { + QMutexLocker locker{&m_mutex}; + m_jobs.insert(path, job); // Insertion is always successful + } + emit JobNew(path, source); + registerObjectToDbus(job.data(), objectPath, getDBusInterface()); + auto emitRemove = [this, job, path, future] { + decltype(m_jobs)::size_type removeCount{0}; + { + QMutexLocker locker{&m_mutex}; + removeCount = m_jobs.remove(path); + } + // removeCount means m_jobs can't find value which corresponding with path + // and we shouldn't emit jobRemoved signal because this signal may already has been emit + if (removeCount == 0) { + qCritical() << "Job already has been removed: " << path.path(); + return; + } + QString result{job->status()}; + for (const auto &val : future.result()) { + if (val.canConvert()) { + result = "failed"; + } + break; + } + emit this->JobRemoved(path, result, future.result()); + }; + future.then(QtFuture::Launch::Sync, emitRemove); + } Q_SIGNALS: void JobNew(const QDBusObjectPath &job, const QDBusObjectPath &source); - void JobRemoved(const QDBusObjectPath &job, const QString &status, const QString &message, const QDBusVariant &result); + void JobRemoved(const QDBusObjectPath &job, const QString &status, const QVariantList &result); private: + QMutex m_mutex; QMap> m_jobs; }; diff --git a/src/dbus/jobservice.cpp b/src/dbus/jobservice.cpp index 312d99c..c234a21 100644 --- a/src/dbus/jobservice.cpp +++ b/src/dbus/jobservice.cpp @@ -4,7 +4,7 @@ #include "jobservice.h" -JobService::JobService(const QFuture& job) +JobService::JobService(const QFuture& job) : m_job(job) { } @@ -31,7 +31,7 @@ QString JobService::status() const if (m_job.isRunning()) { return "running"; } - return "failed"; + Q_UNREACHABLE(); } void JobService::Cancel() @@ -39,7 +39,7 @@ void JobService::Cancel() m_job.cancel(); } -void JobService::Pause() +void JobService::Suspend() { m_job.suspend(); } diff --git a/src/dbus/jobservice.h b/src/dbus/jobservice.h index fcbd4a8..0fac737 100644 --- a/src/dbus/jobservice.h +++ b/src/dbus/jobservice.h @@ -14,18 +14,23 @@ class JobService : public QObject Q_OBJECT public: ~JobService() override; + JobService(const JobService &) = delete; + JobService(JobService &&) = delete; + JobService &operator=(const JobService &) = delete; + JobService &operator=(JobService &&) = delete; Q_PROPERTY(QString Status READ status) QString status() const; public Q_SLOTS: void Cancel(); - void Pause(); + void Suspend(); void Resume(); private: - explicit JobService(const QFuture& job); - QFuture m_job; + friend class JobManager1Service; + explicit JobService(const QFuture& job); + QFuture m_job; }; #endif diff --git a/src/include/global.h b/src/include/global.h index 6207cbb..e31d2c9 100644 --- a/src/include/global.h +++ b/src/include/global.h @@ -62,7 +62,7 @@ bool registerObjectToDbus(T parent, const QString &path, const QString &interfac "param type must derive QObject"); auto &con = ApplicationManager1DBus::instance().CustomBus(); if (!con.registerObject(path, interface, new U{parent})) { - qWarning() << "register object failed:" << path << interface << con.lastError(); + qCritical() << "register object failed:" << path << interface << con.lastError(); return false; } return true;