aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/GpgContext.cpp73
-rw-r--r--src/core/GpgContext.h5
-rw-r--r--src/core/GpgInfo.h27
-rw-r--r--src/core/function/gpg/GpgCommandExecutor.cpp126
-rw-r--r--src/core/function/gpg/GpgCommandExecutor.h7
-rw-r--r--src/core/thread/CtxCheckTask.cpp3
-rw-r--r--src/core/thread/FileReadTask.cpp2
-rw-r--r--src/core/thread/Task.cpp54
-rw-r--r--src/core/thread/Task.h27
-rw-r--r--src/core/thread/TaskRunner.cpp45
-rw-r--r--src/core/thread/TaskRunner.h1
-rw-r--r--src/ui/UserInterfaceUtils.cpp22
-rw-r--r--src/ui/dialog/help/GnupgTab.cpp7
-rw-r--r--src/ui/thread/KeyServerImportTask.cpp3
-rw-r--r--src/ui/thread/KeyServerSearchTask.cpp3
-rw-r--r--src/ui/thread/ListedKeyServerTestTask.cpp3
-rw-r--r--src/ui/thread/VersionCheckTask.cpp3
17 files changed, 315 insertions, 96 deletions
diff --git a/src/core/GpgContext.cpp b/src/core/GpgContext.cpp
index 9f69522a..613767a7 100644
--- a/src/core/GpgContext.cpp
+++ b/src/core/GpgContext.cpp
@@ -32,6 +32,8 @@
#include <gpgme.h>
#include <unistd.h>
+#include <mutex>
+#include <shared_mutex>
#include <string>
#include "core/GpgConstants.h"
@@ -159,10 +161,12 @@ GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) {
// async, init context
Thread::TaskRunnerGetter::GetInstance()
.GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_GPG)
- ->PostTask(new Thread::Task([=](Thread::Task::DataObjectPtr) -> int {
- post_init_ctx();
- return 0;
- }));
+ ->PostTask(new Thread::Task(
+ [=](Thread::Task::DataObjectPtr) -> int {
+ post_init_ctx();
+ return 0;
+ },
+ "post_init_ctx"));
good_ = true;
}
@@ -213,7 +217,7 @@ void GpgContext::post_init_ctx() {
}
// preload info
- auto info = GetInfo();
+ auto &info = GetInfo();
// listen passphrase input event
SetPassphraseCb(custom_passphrase_cb);
@@ -321,6 +325,15 @@ std::string GpgContext::need_user_input_passphrase() {
const GpgInfo &GpgContext::GetInfo(bool refresh) {
if (!extend_info_loaded_ || refresh) {
+ // try lock
+ std::unique_lock lock(preload_lock_);
+
+ // check twice
+ if (extend_info_loaded_ && !refresh) return info_;
+
+ SPDLOG_DEBUG("start to load extra info");
+
+ // get all components
GpgCommandExecutor::GetInstance().Execute(
info_.GpgConfPath, {"--list-components"},
[=](int exit_code, const std::string &p_out, const std::string &p_err) {
@@ -382,13 +395,19 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) {
info_.KeyboxdPath = info_split_list[2];
}
- // add component info to list
- components_info[component_name] = {
- component_desc, version, component_path,
- binary_checksum.has_value() ? binary_checksum.value() : "/"};
+ {
+ // try lock
+ std::unique_lock lock(info_.Lock);
+ // add component info to list
+ components_info[component_name] = {
+ component_desc, version, component_path,
+ binary_checksum.has_value() ? binary_checksum.value() : "/"};
+ }
}
});
+ SPDLOG_DEBUG("start to get dirs info");
+
GpgCommandExecutor::GetInstance().Execute(
info_.GpgConfPath, {"--list-dirs"},
[=](int exit_code, const std::string &p_out, const std::string &p_err) {
@@ -423,10 +442,16 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) {
}
auto configuration_name = info_split_list[0];
- configurations_info[configuration_name] = {info_split_list[1]};
+ {
+ // try lock
+ std::unique_lock lock(info_.Lock);
+ configurations_info[configuration_name] = {info_split_list[1]};
+ }
}
});
+ SPDLOG_DEBUG("start to get components info");
+
for (const auto &component : info_.ComponentsInfo) {
SPDLOG_DEBUG("gpgconf check options ready", "component", component.first);
@@ -464,13 +489,19 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) {
if (info_split_list.size() != 6) continue;
auto configuration_name = info_split_list[0];
- options_info[configuration_name] = {
- info_split_list[1], info_split_list[2], info_split_list[3],
- info_split_list[4], info_split_list[5]};
+ {
+ // try lock
+ std::unique_lock lock(info_.Lock);
+ options_info[configuration_name] = {
+ info_split_list[1], info_split_list[2], info_split_list[3],
+ info_split_list[4], info_split_list[5]};
+ }
}
});
}
+ SPDLOG_DEBUG("start to get component options info");
+
for (const auto &component : info_.ComponentsInfo) {
SPDLOG_DEBUG("gpgconf list options ready", "component", component.first);
@@ -508,16 +539,22 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) {
if (info_split_list.size() != 10) continue;
auto configuration_name = info_split_list[0];
- available_options_info[configuration_name] = {
- info_split_list[1], info_split_list[2], info_split_list[3],
- info_split_list[4], info_split_list[5], info_split_list[6],
- info_split_list[7], info_split_list[8], info_split_list[9]};
+ {
+ // try lock
+ std::unique_lock lock(info_.Lock);
+ available_options_info[configuration_name] = {
+ info_split_list[1], info_split_list[2], info_split_list[3],
+ info_split_list[4], info_split_list[5], info_split_list[6],
+ info_split_list[7], info_split_list[8], info_split_list[9]};
+ }
}
});
}
-
extend_info_loaded_ = true;
}
+
+ // ensure nothing is changing now
+ std::shared_lock lock(preload_lock_);
return info_;
}
diff --git a/src/core/GpgContext.h b/src/core/GpgContext.h
index 79d76fe2..384271a6 100644
--- a/src/core/GpgContext.h
+++ b/src/core/GpgContext.h
@@ -107,9 +107,10 @@ class GPGFRONTEND_CORE_EXPORT GpgContext
operator gpgme_ctx_t() const { return _ctx_ref.get(); }
private:
- GpgInfo info_; ///<
- GpgContextInitArgs args_; ///<
+ GpgInfo info_{}; ///<
+ GpgContextInitArgs args_{}; ///<
bool extend_info_loaded_ = false;
+ std::shared_mutex preload_lock_{};
/**
* @brief
diff --git a/src/core/GpgInfo.h b/src/core/GpgInfo.h
index 115b7911..f4415af1 100644
--- a/src/core/GpgInfo.h
+++ b/src/core/GpgInfo.h
@@ -29,6 +29,7 @@
#ifndef GPGFRONTEND_ZH_CN_TS_GPGINFO_H
#define GPGFRONTEND_ZH_CN_TS_GPGINFO_H
+#include <mutex>
#include <string>
namespace GpgFrontend {
@@ -38,22 +39,26 @@ namespace GpgFrontend {
*/
class GpgInfo {
public:
- std::string AppPath; ///< executable binary path of gnupg
- std::string DatabasePath; ///<
- std::string GnupgVersion; ///<
- std::string GpgConfPath; ///<
- std::string AssuanPath; ///<
- std::string CMSPath; ///<
- std::string GpgAgentPath; ///<
- std::string DirmngrPath; ///<
- std::string KeyboxdPath; ///<
- std::string GpgMEVersion; ///<
- std::string GnuPGHomePath; ///<
+ std::string GnupgVersion; ///< version of gnupg
+ std::string GpgMEVersion; ///<
+
+ std::string AppPath; ///< executable binary path of gnupg
+ std::string DatabasePath; ///< key database path
+ std::string GpgConfPath; ///< executable binary path of gpgconf
+ std::string AssuanPath; ///< executable binary path of assuan
+ std::string CMSPath; ///< executable binary path of cms
+ std::string GpgAgentPath; ///< executable binary path of gpg-agent
+ std::string DirmngrPath; ///< executable binary path of dirmgr
+ std::string KeyboxdPath; ///< executable binary path of keyboxd
+
+ std::string GnuPGHomePath; ///< value of ---homedir
std::map<std::string, std::vector<std::string>> ComponentsInfo; ///<
std::map<std::string, std::vector<std::string>> ConfigurationsInfo; ///<
std::map<std::string, std::vector<std::string>> OptionsInfo; ///<
std::map<std::string, std::vector<std::string>> AvailableOptionsInfo; ///<
+
+ std::shared_mutex Lock;
};
} // namespace GpgFrontend
diff --git a/src/core/function/gpg/GpgCommandExecutor.cpp b/src/core/function/gpg/GpgCommandExecutor.cpp
index 670dae0c..30984697 100644
--- a/src/core/function/gpg/GpgCommandExecutor.cpp
+++ b/src/core/function/gpg/GpgCommandExecutor.cpp
@@ -29,6 +29,7 @@
#include "GpgFunctionObject.h"
#include "core/thread/TaskRunnerGetter.h"
+#include "spdlog/fmt/bundled/format.h"
GpgFrontend::GpgCommandExecutor::GpgCommandExecutor(int channel)
: SingletonFunctionObject<GpgCommandExecutor>(channel) {}
@@ -79,9 +80,8 @@ void GpgFrontend::GpgCommandExecutor::Execute(
[interact_func, cmd_process]() { interact_func(cmd_process); });
QObject::connect(cmd_process, &QProcess::errorOccurred,
[=](QProcess::ProcessError error) {
- SPDLOG_ERROR(
- "error in executing command: {} error: {}",
- cmd, error);
+ SPDLOG_ERROR("error in executing command: {} error: {}",
+ cmd, error);
});
QObject::connect(
cmd_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
@@ -94,7 +94,8 @@ void GpgFrontend::GpgCommandExecutor::Execute(
else
SPDLOG_ERROR(
"proceess finished, error in executing command: {}, exit "
- "status: {}", cmd, status);
+ "status: {}",
+ cmd, status);
});
cmd_process->setProgram(QString::fromStdString(cmd));
@@ -104,7 +105,8 @@ void GpgFrontend::GpgCommandExecutor::Execute(
q_arguments.append(QString::fromStdString(argument));
cmd_process->setArguments(q_arguments);
- SPDLOG_DEBUG("process execute ready");
+ SPDLOG_DEBUG("process execute ready, cmd: {} {}", cmd,
+ q_arguments.join(" ").toStdString());
cmd_process->start();
cmd_process->waitForFinished();
@@ -131,10 +133,11 @@ void GpgFrontend::GpgCommandExecutor::Execute(
data_object->AppendObject(std::move(callback));
data_object->AppendObject(std::move(interact_func));
data_object->AppendObject(std::move(arguments));
- data_object->AppendObject(std::move(cmd));
+ data_object->AppendObject(std::move(std::string{cmd}));
auto *process_task = new GpgFrontend::Thread::Task(
- std::move(runner), std::move(result_callback), data_object);
+ std::move(runner), fmt::format("Execute/{}", cmd), data_object,
+ std::move(result_callback));
QEventLoop looper;
QObject::connect(process_task, &Thread::Task::SignalTaskFinished, &looper,
@@ -148,3 +151,112 @@ void GpgFrontend::GpgCommandExecutor::Execute(
// this is to keep reference vaild until task finished
looper.exec();
}
+
+void GpgFrontend::GpgCommandExecutor::ExecuteConcurrently(
+ std::string cmd, std::vector<std::string> arguments,
+ std::function<void(int, std::string, std::string)> callback,
+ std::function<void(QProcess *)> interact_func) {
+ SPDLOG_DEBUG("called cmd {} arguments size: {}", cmd, arguments.size());
+
+ Thread::Task::TaskCallback result_callback =
+ [](int rtn, Thread::Task::DataObjectPtr data_object) {
+ if (data_object->GetObjectSize() != 4)
+ throw std::runtime_error("invalid data object size");
+
+ auto exit_code = data_object->PopObject<int>();
+ auto process_stdout = data_object->PopObject<std::string>();
+ auto process_stderr = data_object->PopObject<std::string>();
+ auto callback = data_object->PopObject<
+ std::function<void(int, std::string, std::string)>>();
+
+ // call callback
+ callback(exit_code, process_stdout, process_stderr);
+ };
+
+ Thread::Task::TaskRunnable runner =
+ [](GpgFrontend::Thread::Task::DataObjectPtr data_object) -> int {
+ SPDLOG_DEBUG("process runner called, data object size: {}",
+ data_object->GetObjectSize());
+
+ if (data_object->GetObjectSize() != 4)
+ throw std::runtime_error("invalid data object size");
+
+ // get arguments
+ auto cmd = data_object->PopObject<std::string>();
+ auto arguments = data_object->PopObject<std::vector<std::string>>();
+ auto interact_func =
+ data_object->PopObject<std::function<void(QProcess *)>>();
+
+ auto *cmd_process = new QProcess();
+ cmd_process->setProcessChannelMode(QProcess::MergedChannels);
+
+ QObject::connect(cmd_process, &QProcess::started,
+ []() -> void { SPDLOG_DEBUG("process started"); });
+ QObject::connect(
+ cmd_process, &QProcess::readyReadStandardOutput,
+ [interact_func, cmd_process]() { interact_func(cmd_process); });
+ QObject::connect(cmd_process, &QProcess::errorOccurred,
+ [=](QProcess::ProcessError error) {
+ SPDLOG_ERROR("error in executing command: {} error: {}",
+ cmd, error);
+ });
+ QObject::connect(
+ cmd_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
+ [=](int, QProcess::ExitStatus status) {
+ if (status == QProcess::NormalExit)
+ SPDLOG_DEBUG(
+ "proceess finished, succeed in executing command: {}, exit "
+ "status: {}",
+ cmd, status);
+ else
+ SPDLOG_ERROR(
+ "proceess finished, error in executing command: {}, exit "
+ "status: {}",
+ cmd, status);
+ });
+
+ cmd_process->setProgram(QString::fromStdString(cmd));
+
+ QStringList q_arguments;
+ for (const auto &argument : arguments)
+ q_arguments.append(QString::fromStdString(argument));
+ cmd_process->setArguments(q_arguments);
+
+ SPDLOG_DEBUG("process start ready, cmd: {} {}", cmd,
+ q_arguments.join(" ").toStdString());
+
+ cmd_process->start();
+ cmd_process->waitForFinished();
+
+ std::string process_stdout =
+ cmd_process->readAllStandardOutput().toStdString(),
+ process_stderr =
+ cmd_process->readAllStandardError().toStdString();
+ int exit_code = cmd_process->exitCode();
+
+ cmd_process->close();
+ cmd_process->deleteLater();
+
+ // transfer result
+ data_object->AppendObject(std::move(process_stderr));
+ data_object->AppendObject(std::move(process_stdout));
+ data_object->AppendObject(std::move(exit_code));
+
+ return 0;
+ };
+
+ // data transfer into task
+ auto data_object = std::make_shared<Thread::Task::DataObject>();
+ data_object->AppendObject(std::move(callback));
+ data_object->AppendObject(std::move(interact_func));
+ data_object->AppendObject(std::move(arguments));
+ data_object->AppendObject(std::move(std::string{cmd}));
+
+ auto *process_task = new GpgFrontend::Thread::Task(
+ std::move(runner), fmt::format("ExecuteConcurrently/{}", cmd),
+ data_object, std::move(result_callback), false);
+
+ GpgFrontend::Thread::TaskRunnerGetter::GetInstance()
+ .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_External_Process)
+ ->PostTask(process_task);
+}
diff --git a/src/core/function/gpg/GpgCommandExecutor.h b/src/core/function/gpg/GpgCommandExecutor.h
index c597feac..da0e7a8b 100644
--- a/src/core/function/gpg/GpgCommandExecutor.h
+++ b/src/core/function/gpg/GpgCommandExecutor.h
@@ -55,7 +55,7 @@ class GPGFRONTEND_CORE_EXPORT GpgCommandExecutor
int channel = SingletonFunctionObject::GetDefaultChannel());
/**
- * @brief Excuting an order
+ * @brief Excuting a command
*
* @param arguments Command parameters
* @param interact_func Command answering function
@@ -66,6 +66,11 @@ class GPGFRONTEND_CORE_EXPORT GpgCommandExecutor
[](int, std::string, std::string) {},
std::function<void(QProcess *)> interact_func = [](QProcess *) {});
+ void ExecuteConcurrently(
+ std::string cmd, std::vector<std::string> arguments,
+ std::function<void(int, std::string, std::string)> callback,
+ std::function<void(QProcess *)> interact_func = [](QProcess *) {});
+
private:
GpgContext &ctx_ = GpgContext::GetInstance(
SingletonFunctionObject::GetChannel()); ///< Corresponding context
diff --git a/src/core/thread/CtxCheckTask.cpp b/src/core/thread/CtxCheckTask.cpp
index 997dd341..eef05b1b 100644
--- a/src/core/thread/CtxCheckTask.cpp
+++ b/src/core/thread/CtxCheckTask.cpp
@@ -30,8 +30,9 @@
#include "core/GpgCoreInit.h"
#include "core/common/CoreCommonUtil.h"
#include "core/function/gpg/GpgKeyGetter.h"
+#include "thread/Task.h"
-GpgFrontend::Thread::CtxCheckTask::CtxCheckTask() {
+GpgFrontend::Thread::CtxCheckTask::CtxCheckTask() : Task("ctx_check_task") {
connect(this, &CtxCheckTask::SignalGnupgNotInstall,
CoreCommonUtil::GetInstance(),
&CoreCommonUtil::SignalGnupgNotInstall);
diff --git a/src/core/thread/FileReadTask.cpp b/src/core/thread/FileReadTask.cpp
index 0f7d11c3..0888e029 100644
--- a/src/core/thread/FileReadTask.cpp
+++ b/src/core/thread/FileReadTask.cpp
@@ -28,7 +28,7 @@
namespace GpgFrontend::UI {
-FileReadTask::FileReadTask(std::string path) {
+FileReadTask::FileReadTask(std::string path) : Task("file_read_task") {
connect(this, &FileReadTask::SignalFileBytesReadNext, this,
&FileReadTask::read_bytes);
diff --git a/src/core/thread/Task.cpp b/src/core/thread/Task.cpp
index 87be7a10..823276ae 100644
--- a/src/core/thread/Task.cpp
+++ b/src/core/thread/Task.cpp
@@ -35,39 +35,61 @@
#include "core/thread/TaskRunner.h"
-GpgFrontend::Thread::Task::Task() : uuid_(generate_uuid()) {
- SPDLOG_TRACE("task {} created", uuid_);
+const std::string GpgFrontend::Thread::Task::DEFAULT_TASK_NAME = "default-task";
+
+GpgFrontend::Thread::Task::Task(std::string name)
+ : uuid_(generate_uuid()), name_(name) {
+ SPDLOG_TRACE("task {}/ created", GetFullID());
init();
}
-GpgFrontend::Thread::Task::Task(TaskCallback callback,
- DataObjectPtr data_object)
+GpgFrontend::Thread::Task::Task(TaskRunnable runnable, std::string name,
+ DataObjectPtr data_object, bool sequency)
: uuid_(generate_uuid()),
- callback_(std::move(callback)),
+ name_(name),
+ runnable_(std::move(runnable)),
+ callback_(std::move([](int, const std::shared_ptr<DataObject> &) {})),
callback_thread_(QThread::currentThread()),
- data_object_(data_object) {
- SPDLOG_TRACE("task {} created with callback, callback_thread_: {}", uuid_,
- static_cast<void *>(callback_thread_));
+ data_object_(data_object),
+ sequency_(sequency) {
+ SPDLOG_TRACE("task {} created with runnable, callback_thread_: {}",
+ GetFullID(), static_cast<void *>(callback_thread_));
init();
}
-GpgFrontend::Thread::Task::Task(TaskRunnable runnable, TaskCallback callback,
- DataObjectPtr data_object)
+GpgFrontend::Thread::Task::Task(TaskRunnable runnable, std::string name,
+ DataObjectPtr data_object,
+ TaskCallback callback, bool sequency)
: uuid_(generate_uuid()),
+ name_(name),
runnable_(std::move(runnable)),
callback_(std::move(callback)),
callback_thread_(QThread::currentThread()),
- data_object_(data_object) {
+ data_object_(data_object),
+ sequency_(sequency) {
init();
SPDLOG_TRACE(
- "task {} created with runnable and callback, callback_thread_: {}", uuid_,
- static_cast<void *>(callback_thread_));
+ "task {} created with runnable and callback, callback_thread_: {}",
+ GetFullID(), static_cast<void *>(callback_thread_));
+}
+
+GpgFrontend::Thread::Task::~Task() {
+ SPDLOG_TRACE("task {} destroyed", GetFullID());
}
-GpgFrontend::Thread::Task::~Task() { SPDLOG_TRACE("task {} destroyed", uuid_); }
+/**
+ * @brief
+ *
+ * @return std::string
+ */
+std::string GpgFrontend::Thread::Task::GetFullID() const {
+ return uuid_ + "/" + name_;
+}
std::string GpgFrontend::Thread::Task::GetUUID() const { return uuid_; }
+bool GpgFrontend::Thread::Task::GetSequency() const { return sequency_; }
+
void GpgFrontend::Thread::Task::SetFinishAfterRun(bool finish_after_run) {
this->finish_after_run_ = finish_after_run;
}
@@ -79,7 +101,7 @@ void GpgFrontend::Thread::Task::init() {
}
void GpgFrontend::Thread::Task::before_finish_task() {
- SPDLOG_TRACE("task {} finished", uuid_);
+ SPDLOG_TRACE("task {} finished", GetFullID());
try {
if (callback_) {
@@ -101,7 +123,7 @@ void GpgFrontend::Thread::Task::before_finish_task() {
}
void GpgFrontend::Thread::Task::run() {
- SPDLOG_TRACE("task {} started", uuid_);
+ SPDLOG_TRACE("task {} started", GetFullID());
Run();
if (finish_after_run_) emit SignalTaskFinished();
}
diff --git a/src/core/thread/Task.h b/src/core/thread/Task.h
index d9a70618..d239cfee 100644
--- a/src/core/thread/Task.h
+++ b/src/core/thread/Task.h
@@ -50,6 +50,8 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
using TaskRunnable = std::function<int(DataObjectPtr)>; ///<
using TaskCallback = std::function<void(int, DataObjectPtr)>; ///<
+ static const std::string DEFAULT_TASK_NAME;
+
friend class TaskRunner;
/**
@@ -164,14 +166,15 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
* @brief Construct a new Task object
*
*/
- Task();
+ Task(std::string name = DEFAULT_TASK_NAME);
/**
* @brief Construct a new Task object
*
* @param callback The callback function to be executed.
*/
- explicit Task(TaskCallback callback, DataObjectPtr data_object = nullptr);
+ explicit Task(TaskRunnable runnable, std::string name = DEFAULT_TASK_NAME,
+ DataObjectPtr data_object = nullptr, bool sequency = true);
/**
* @brief Construct a new Task object
@@ -179,9 +182,9 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
* @param runnable
*/
explicit Task(
- TaskRunnable runnable,
+ TaskRunnable runnable, std::string name, DataObjectPtr data,
TaskCallback callback = [](int, const std::shared_ptr<DataObject> &) {},
- DataObjectPtr data = nullptr);
+ bool sequency = true);
/**
* @brief Destroy the Task object
@@ -202,6 +205,20 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
*/
std::string GetUUID() const;
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ std::string GetFullID() const;
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ bool GetSequency() const;
+
signals:
/**
* @brief
@@ -232,6 +249,8 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
private:
const std::string uuid_;
+ const std::string name_;
+ const bool sequency_ = true; ///< must run in the same thread
TaskCallback callback_; ///<
TaskRunnable runnable_; ///<
bool finish_after_run_ = true; ///<
diff --git a/src/core/thread/TaskRunner.cpp b/src/core/thread/TaskRunner.cpp
index dc6ac385..29aad68b 100644
--- a/src/core/thread/TaskRunner.cpp
+++ b/src/core/thread/TaskRunner.cpp
@@ -34,23 +34,29 @@ GpgFrontend::Thread::TaskRunner::TaskRunner() = default;
GpgFrontend::Thread::TaskRunner::~TaskRunner() = default;
void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) {
- if (task == nullptr) return;
+ if (task == nullptr) {
+ SPDLOG_ERROR("task posted is null");
+ return;
+ }
- std::string uuid = task->GetUUID();
- SPDLOG_TRACE("post task: {}", uuid);
+ SPDLOG_TRACE("post task: {}", task->GetFullID());
task->setParent(nullptr);
task->moveToThread(this);
- connect(task, &Task::SignalTaskPostFinishedDone, this, [&, uuid]() {
- auto it = pending_tasks_.find(uuid);
- if (it == pending_tasks_.end()) {
+ connect(task, &Task::SignalTaskPostFinishedDone, this, [&, this, task]() {
+ SPDLOG_DEBUG("cleaning task {}", task->GetFullID());
+ auto pending_task = pending_tasks_.find(task->GetUUID());
+ if (pending_task == pending_tasks_.end()) {
+ SPDLOG_ERROR("cannot find task in pending list: {}", task->GetFullID());
return;
} else {
- it->second->deleteLater();
- pending_tasks_.erase(it);
+ std::lock_guard<std::mutex> lock(tasks_mutex_);
+ pending_tasks_.erase(pending_task);
}
+ task->deleteLater();
});
+
{
std::lock_guard<std::mutex> lock(tasks_mutex_);
tasks.push(task);
@@ -83,24 +89,29 @@ void GpgFrontend::Thread::TaskRunner::PostScheduleTask(Task* task,
}
if (task != nullptr) {
- // Run the task
- SPDLOG_TRACE("task runner: running task {}", task->GetUUID());
try {
- task->run();
+ // Run the task
+ SPDLOG_TRACE("task runner: running task {}, sequency: {}",
+ task->GetFullID(), task->GetSequency());
+ if (task->GetSequency()) {
+ // run sequently
+ task->run();
+ } else {
+ // run concurrently
+ thread_pool_.start(task);
+ }
} catch (const std::exception& e) {
SPDLOG_ERROR("task runner: exception in task {}, exception: {}",
- task->GetUUID(), e.what());
-
+ task->GetFullID(), e.what());
// destroy the task, remove the task from the pending tasks
- task->deleteLater();
pending_tasks_.erase(task->GetUUID());
+ task->deleteLater();
} catch (...) {
SPDLOG_ERROR("task runner: unknown exception in task: {}",
- task->GetUUID());
-
+ task->GetFullID());
// destroy the task, remove the task from the pending tasks
- task->deleteLater();
pending_tasks_.erase(task->GetUUID());
+ task->deleteLater();
}
}
}
diff --git a/src/core/thread/TaskRunner.h b/src/core/thread/TaskRunner.h
index 6a5e00a5..fff5c368 100644
--- a/src/core/thread/TaskRunner.h
+++ b/src/core/thread/TaskRunner.h
@@ -79,6 +79,7 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread {
std::queue<Task*> tasks; ///< The task queue
std::map<std::string, Task*> pending_tasks_; ///< The pending tasks
std::mutex tasks_mutex_; ///< The task queue mutex
+ QThreadPool thread_pool_{this}; ///< run non-sequency task
};
} // namespace GpgFrontend::Thread
diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp
index 408a1c04..6c3b0726 100644
--- a/src/ui/UserInterfaceUtils.cpp
+++ b/src/ui/UserInterfaceUtils.cpp
@@ -120,8 +120,8 @@ void process_operation(QWidget *parent, const std::string &waiting_title,
auto *dialog =
new WaitingDialog(QString::fromStdString(waiting_title), parent);
- auto *process_task =
- new Thread::Task(std::move(func), std::move(callback), data_object);
+ auto *process_task = new Thread::Task(std::move(func), waiting_title,
+ data_object, std::move(callback));
QApplication::connect(process_task, &Thread::Task::SignalTaskFinished, dialog,
&QDialog::close);
@@ -398,13 +398,15 @@ void CommonUtils::SlotImportKeyFromKeyServer(
}
void CommonUtils::slot_update_key_status() {
- auto refresh_task = new Thread::Task([](Thread::Task::DataObjectPtr) -> int {
- // flush key cache for all GpgKeyGetter Intances.
- for (const auto &channel_id : GpgKeyGetter::GetAllChannelId()) {
- GpgKeyGetter::GetInstance(channel_id).FlushKeyCache();
- }
- return 0;
- });
+ auto refresh_task = new Thread::Task(
+ [](Thread::Task::DataObjectPtr) -> int {
+ // flush key cache for all GpgKeyGetter Intances.
+ for (const auto &channel_id : GpgKeyGetter::GetAllChannelId()) {
+ GpgKeyGetter::GetInstance(channel_id).FlushKeyCache();
+ }
+ return 0;
+ },
+ "update_key_status_task");
connect(refresh_task, &Thread::Task::SignalTaskFinished, this,
&CommonUtils::SignalKeyDatabaseRefreshDone);
@@ -419,7 +421,7 @@ void CommonUtils::slot_popup_passphrase_input_dialog() {
dialog->setWindowTitle(_("Password Input Dialog"));
dialog->setInputMode(QInputDialog::TextInput);
dialog->setTextEchoMode(QLineEdit::Password);
- dialog->setLabelText("Please Input The Password");
+ dialog->setLabelText(_("Please Input The Password"));
dialog->resize(500, 80);
dialog->exec();
diff --git a/src/ui/dialog/help/GnupgTab.cpp b/src/ui/dialog/help/GnupgTab.cpp
index 92c3fd55..5d84ec65 100644
--- a/src/ui/dialog/help/GnupgTab.cpp
+++ b/src/ui/dialog/help/GnupgTab.cpp
@@ -31,14 +31,13 @@
#include "GnupgTab.h"
+#include <shared_mutex>
+
#include "ui/UserInterfaceUtils.h"
#include "ui_GnuPGInfo.h"
GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent)
: QWidget(parent), ui_(std::make_shared<Ui_GnuPGInfo>()) {
- GpgContext& ctx = GpgContext::GetInstance();
- auto info = ctx.GetInfo(false);
-
ui_->setupUi(this);
QStringList components_column_titles;
@@ -77,7 +76,7 @@ GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent)
}
void GpgFrontend::UI::GnupgTab::process_software_info() {
- auto ctx_info = GpgContext::GetInstance().GetInfo(true);
+ auto& ctx_info = GpgContext::GetInstance().GetInfo(true);
ui_->gnupgVersionLabel->setText(QString::fromStdString(
fmt::format("Version: {}", ctx_info.GnupgVersion)));
diff --git a/src/ui/thread/KeyServerImportTask.cpp b/src/ui/thread/KeyServerImportTask.cpp
index bf3e1822..b02a4487 100644
--- a/src/ui/thread/KeyServerImportTask.cpp
+++ b/src/ui/thread/KeyServerImportTask.cpp
@@ -30,7 +30,8 @@
GpgFrontend::UI::KeyServerImportTask::KeyServerImportTask(
std::string keyserver_url, std::vector<std::string> keyids)
- : keyserver_url_(std::move(keyserver_url)),
+ : Task("key_server_import_task"),
+ keyserver_url_(std::move(keyserver_url)),
keyids_(std::move(keyids)),
manager_(new QNetworkAccessManager(this)) {}
diff --git a/src/ui/thread/KeyServerSearchTask.cpp b/src/ui/thread/KeyServerSearchTask.cpp
index 0090e79d..1f90565f 100644
--- a/src/ui/thread/KeyServerSearchTask.cpp
+++ b/src/ui/thread/KeyServerSearchTask.cpp
@@ -30,7 +30,8 @@
GpgFrontend::UI::KeyServerSearchTask::KeyServerSearchTask(
std::string keyserver_url, std::string search_string)
- : keyserver_url_(std::move(keyserver_url)),
+ : Task("key_server_search_task"),
+ keyserver_url_(std::move(keyserver_url)),
search_string_(std::move(search_string)),
manager_(new QNetworkAccessManager(this)) {}
diff --git a/src/ui/thread/ListedKeyServerTestTask.cpp b/src/ui/thread/ListedKeyServerTestTask.cpp
index 17bb0356..fe87ed06 100644
--- a/src/ui/thread/ListedKeyServerTestTask.cpp
+++ b/src/ui/thread/ListedKeyServerTestTask.cpp
@@ -30,7 +30,8 @@
GpgFrontend::UI::ListedKeyServerTestTask::ListedKeyServerTestTask(
const QStringList& urls, int timeout, QWidget* parent)
- : urls_(urls),
+ : Task("listed_key_server_test_task"),
+ urls_(urls),
timeout_(timeout),
network_manager_(new QNetworkAccessManager(this)),
result_(urls_.size(), kTestResultType_Error) {
diff --git a/src/ui/thread/VersionCheckTask.cpp b/src/ui/thread/VersionCheckTask.cpp
index 45fe8c80..08571223 100644
--- a/src/ui/thread/VersionCheckTask.cpp
+++ b/src/ui/thread/VersionCheckTask.cpp
@@ -36,7 +36,8 @@
namespace GpgFrontend::UI {
VersionCheckTask::VersionCheckTask()
- : network_manager_(new QNetworkAccessManager(this)),
+ : Task("version_check_task"),
+ network_manager_(new QNetworkAccessManager(this)),
current_version_(std::string("v") + std::to_string(VERSION_MAJOR) + "." +
std::to_string(VERSION_MINOR) + "." +
std::to_string(VERSION_PATCH)) {