feat: finish dbus service: job/jobManager

Log:
This commit is contained in:
heyuming 2023-07-18 15:55:29 +08:00 committed by Comix
parent 3a278bec79
commit d288752fb3
9 changed files with 72 additions and 41 deletions

View File

@ -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)

View File

@ -7,7 +7,7 @@
value="Value of `Status` is one of
`started`, `running`, `finished`,
`suspending`, `suspend`,
`canceled` and `failed`."
`canceled`."
/>
</property>
@ -22,13 +22,13 @@
will be emitted."
/>
</method>
<method name="Pause">
<method name="Suspend">
<annotation
name="org.freedesktop.DBus.Description"
value="Success call to this method will
change the Status of this Job to `pausing`.
change the Status of this Job to `suspending`.
Then after some time this method call return,
Status will change to `paused`."
Status will change to `suspend`."
/>
</method>
@ -36,8 +36,7 @@
<annotation
name="org.freedesktop.DBus.Description"
value="Success call to this method will
change the Status of this Job to `resuming`.
Resuming Jobs will be queued along with pending Jobs.
Resumes the asynchronous computation.
Then after some time this method call return,
Status will change to `working`."
/>

View File

@ -26,17 +26,16 @@
<signal name="JobRemoved">
<arg type="o" name="job" />
<arg type="s" name="status" />
<arg type="s" name="message" />
<arg type="v" name="result" />
<arg type="av" name="result" />
<annotation
name="org.freedesktop.DBus.Description"
value="This signal report the job remove event.
`status` is the `status` porperty of that Job
when it got removed.
`message` is the human readable message
for caller to report to user or just simple logging.
`result` is the result this job produce if it success.
`result` is the result which produce by this job,
and user needs to traverse the list to determine
if the values are valid or not.
Method that return an object of Job
should always have document
about the type and meaning of the `result`."

View File

@ -24,6 +24,7 @@ target_include_directories(${BIN_NAME} PRIVATE
target_link_libraries(${BIN_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::DBus
Qt${QT_VERSION_MAJOR}::Concurrent
Threads::Threads
)

View File

@ -3,24 +3,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "jobmanager1service.h"
#include <QUuid>
#include "global.h"
JobManager1Service::JobManager1Service() = default;
JobManager1Service::~JobManager1Service() = default;
template <typename F, typename... Args>
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;
}

View File

@ -9,7 +9,14 @@
#include <QMap>
#include <QDBusObjectPath>
#include <QSharedPointer>
#include "jobservice.h"
#include <QMutex>
#include <QMutexLocker>
#include <QtConcurrent>
#include <QFuture>
#include <QUuid>
#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<typename F,typename ...Args>
void addJob(const QDBusObjectPath &source,F func, Args&& ...args);
bool removeJob(const QDBusObjectPath &job, const QString &status, const QString &message, const QDBusVariant &result);
template <typename F>
void addJob(const QDBusObjectPath &source, F func, QVariantList args)
{
static_assert(std::is_invocable_v<F, QVariant>, "param type must be QVariant.");
QString objectPath{DDEApplicationManager1JobObjectPath + QUuid::createUuid().toString()};
QFuture<QVariantList> future = QtConcurrent::mappedReduced(
args.begin(), args.end(), func, &QVariantList::insert, QVariantList{}, QtConcurrent::ReduceOption::OrderedReduce);
QSharedPointer<JobService> 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<decltype(job.data()), JobAdaptor>(job.data(), objectPath, getDBusInterface<JobAdaptor>());
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<QDBusError>()) {
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<QDBusObjectPath, QSharedPointer<JobService>> m_jobs;
};

View File

@ -4,7 +4,7 @@
#include "jobservice.h"
JobService::JobService(const QFuture<QVariant>& job)
JobService::JobService(const QFuture<QVariantList>& 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();
}

View File

@ -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<QVariant>& job);
QFuture<QVariant> m_job;
friend class JobManager1Service;
explicit JobService(const QFuture<QVariantList>& job);
QFuture<QVariantList> m_job;
};
#endif

View File

@ -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;