aboutsummaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/function/gpg/GpgCommandExecutor.cpp59
-rw-r--r--src/core/function/gpg/GpgCommandExecutor.h5
-rw-r--r--src/core/function/gpg/GpgKeyOpera.cpp1
-rw-r--r--src/core/module/GlobalRegisterTable.cpp55
-rw-r--r--src/core/thread/Task.cpp67
-rw-r--r--src/core/thread/TaskRunnerGetter.cpp16
-rw-r--r--src/core/thread/TaskRunnerGetter.h6
7 files changed, 152 insertions, 57 deletions
diff --git a/src/core/function/gpg/GpgCommandExecutor.cpp b/src/core/function/gpg/GpgCommandExecutor.cpp
index 3fd56d35..fb1d647d 100644
--- a/src/core/function/gpg/GpgCommandExecutor.cpp
+++ b/src/core/function/gpg/GpgCommandExecutor.cpp
@@ -33,14 +33,21 @@
#include "GpgFunctionObject.h"
#include "core/thread/DataObject.h"
#include "core/thread/TaskRunnerGetter.h"
+#include "module/Module.h"
#include "spdlog/spdlog.h"
+#include "thread/Task.h"
namespace GpgFrontend {
GpgCommandExecutor::ExecuteContext::ExecuteContext(
std::string cmd, std::vector<std::string> arguments,
- GpgCommandExecutorCallback callback, GpgCommandExecutorInteractor int_func)
- : cmd(cmd), arguments(arguments), cb_func(callback), int_func(int_func) {}
+ GpgCommandExecutorCallback callback, Module::TaskRunnerPtr task_runner,
+ GpgCommandExecutorInteractor int_func)
+ : cmd(cmd),
+ arguments(arguments),
+ cb_func(callback),
+ int_func(int_func),
+ task_runner(task_runner) {}
GpgCommandExecutor::GpgCommandExecutor(int channel)
: SingletonFunctionObject<GpgCommandExecutor>(channel) {}
@@ -52,13 +59,26 @@ void GpgCommandExecutor::ExecuteSync(ExecuteContext context) {
QObject::connect(task, &Thread::Task::SignalTaskEnd, &looper,
&QEventLoop::quit);
- GpgFrontend::Thread::TaskRunnerGetter::GetInstance()
- .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_External_Process)
- ->PostTask(task);
+ Thread::TaskRunnerPtr target_task_runner = nullptr;
- // block until task finished
- // this is to keep reference vaild until task finished
- looper.exec();
+ if (context.task_runner != nullptr) {
+ target_task_runner = context.task_runner;
+ } else {
+ target_task_runner =
+ GpgFrontend::Thread::TaskRunnerGetter::GetInstance().GetTaskRunner(
+ Thread::TaskRunnerGetter::kTaskRunnerType_External_Process);
+ }
+
+ target_task_runner->PostTask(task);
+
+ // to arvoid dead lock issue we need to check if current thread is the same as
+ // target thread. if it is, we can't call exec() because it will block the
+ // current thread.
+ if (QThread::currentThread() != target_task_runner->GetThread()) {
+ // block until task finished
+ // this is to keep reference vaild until task finished
+ looper.exec();
+ }
}
void GpgCommandExecutor::ExecuteConcurrentlyAsync(ExecuteContexts contexts) {
@@ -67,10 +87,14 @@ void GpgCommandExecutor::ExecuteConcurrentlyAsync(ExecuteContexts contexts) {
SPDLOG_INFO("gpg concurrently called cmd {}", cmd);
Thread::Task *task = build_task_from_exec_ctx(context);
- GpgFrontend::Thread::TaskRunnerGetter::GetInstance()
- .GetTaskRunner(
- Thread::TaskRunnerGetter::kTaskRunnerType_External_Process)
- ->PostTask(task);
+
+ if (context.task_runner != nullptr)
+ context.task_runner->PostTask(task);
+ else
+ GpgFrontend::Thread::TaskRunnerGetter::GetInstance()
+ .GetTaskRunner(
+ Thread::TaskRunnerGetter::kTaskRunnerType_External_Process)
+ ->PostTask(task);
}
}
@@ -92,10 +116,13 @@ void GpgCommandExecutor::ExecuteConcurrentlySync(
}
});
- GpgFrontend::Thread::TaskRunnerGetter::GetInstance()
- .GetTaskRunner(
- Thread::TaskRunnerGetter::kTaskRunnerType_External_Process)
- ->PostConcurrentTask(task);
+ if (context.task_runner != nullptr)
+ context.task_runner->PostTask(task);
+ else
+ GpgFrontend::Thread::TaskRunnerGetter::GetInstance()
+ .GetTaskRunner(
+ Thread::TaskRunnerGetter::kTaskRunnerType_External_Process)
+ ->PostTask(task);
}
looper.exec();
diff --git a/src/core/function/gpg/GpgCommandExecutor.h b/src/core/function/gpg/GpgCommandExecutor.h
index bd356b8b..fc9f2a83 100644
--- a/src/core/function/gpg/GpgCommandExecutor.h
+++ b/src/core/function/gpg/GpgCommandExecutor.h
@@ -29,6 +29,9 @@
#pragma once
#include <initializer_list>
+
+#include "core/module/Module.h"
+#include "core/thread/TaskRunner.h"
#ifndef WINDOWS
#include <boost/process.hpp>
#endif
@@ -55,11 +58,13 @@ class GPGFRONTEND_CORE_EXPORT GpgCommandExecutor
const std::vector<std::string> arguments;
const GpgCommandExecutorCallback cb_func;
const GpgCommandExecutorInteractor int_func;
+ Module::TaskRunnerPtr task_runner = nullptr;
ExecuteContext(
std::string cmd, std::vector<std::string> arguments,
GpgCommandExecutorCallback callback = [](int, std::string,
std::string) {},
+ Module::TaskRunnerPtr task_runner = nullptr,
GpgCommandExecutorInteractor int_func = [](QProcess *) {});
};
diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp
index 1d31bb1d..eb7dfe9f 100644
--- a/src/core/function/gpg/GpgKeyOpera.cpp
+++ b/src/core/function/gpg/GpgKeyOpera.cpp
@@ -123,6 +123,7 @@ void GpgKeyOpera::GenerateRevokeCert(const GpgKey& key,
exit_code, p_out.size());
}
},
+ nullptr,
[](QProcess* proc) -> void {
// Code From Gpg4Win
while (proc->canReadLine()) {
diff --git a/src/core/module/GlobalRegisterTable.cpp b/src/core/module/GlobalRegisterTable.cpp
index 47552eb8..8d28dc34 100644
--- a/src/core/module/GlobalRegisterTable.cpp
+++ b/src/core/module/GlobalRegisterTable.cpp
@@ -40,12 +40,11 @@ namespace GpgFrontend::Module {
class GlobalRegisterTable::Impl {
public:
- struct Value {
- std::any value;
+ struct RTNode {
+ std::optional<std::any> value = std::nullopt;
+ std::unordered_map<std::string, std::unique_ptr<RTNode>> children;
int version = 0;
- const std::type_info& type;
-
- Value(std::any v) : value(v), type(v.type()) {}
+ const std::type_info* type = nullptr; // 保存类型信息
};
Impl(GlobalRegisterTable* parent)
@@ -55,23 +54,26 @@ class GlobalRegisterTable::Impl {
SPDLOG_DEBUG("publishing kv to rt, n: {}, k: {}, v type: {}", n, k,
v.type().name());
+ std::istringstream iss(k);
+ std::string segment;
+
int version = 0;
{
std::unique_lock lock(lock_);
- auto& sub_table =
- global_register_table_.emplace(n, SubTable{}).first->second;
-
- auto sub_it = sub_table.find(k);
- if (sub_it == sub_table.end()) {
- sub_it = sub_table.emplace(k, std::make_unique<Value>(Value{v})).first;
- } else {
- if (sub_it->second->type != v.type()) {
- return false;
- }
- sub_it->second->value = v;
+ auto& root_rt_node =
+ global_register_table_.emplace(n, std::make_unique<RTNode>())
+ .first->second;
+
+ RTNode* current = root_rt_node.get();
+ while (std::getline(iss, segment, '.')) {
+ current = current->children.emplace(segment, std::make_unique<RTNode>())
+ .first->second.get();
}
- version = ++sub_it->second->version;
+
+ current->value = v;
+ current->type = &v.type();
+ current->version++;
}
emit parent_->SignalPublish(n, k, version, v);
@@ -80,17 +82,23 @@ class GlobalRegisterTable::Impl {
std::optional<std::any> LookupKV(Namespace n, Key k) {
SPDLOG_DEBUG("looking up kv in rt, n: {}, k: {}", n, k);
+
+ std::istringstream iss(k);
+ std::string segment;
+
std::optional<std::any> rtn = std::nullopt;
{
std::shared_lock lock(lock_);
auto it = global_register_table_.find(n);
if (it == global_register_table_.end()) return std::nullopt;
- auto& sub_table = it->second;
- auto sub_it = sub_table.find(k);
- rtn = (sub_it != sub_table.end())
- ? std::optional<std::any>{sub_it->second->value}
- : std::nullopt;
+ RTNode* current = it->second.get();
+ while (std::getline(iss, segment, '.')) {
+ auto it = current->children.find(segment);
+ if (it == current->children.end()) return std::nullopt;
+ current = it->second.get();
+ }
+ rtn = current->value;
}
return rtn;
}
@@ -107,8 +115,7 @@ class GlobalRegisterTable::Impl {
}
private:
- using SubTable = std::unordered_map<Key, std::unique_ptr<Value>>;
- using Table = std::map<Namespace, SubTable>;
+ using Table = std::map<Namespace, std::unique_ptr<RTNode>>;
std::shared_mutex lock_;
GlobalRegisterTable* parent_;
diff --git a/src/core/thread/Task.cpp b/src/core/thread/Task.cpp
index ad3d3321..0e0f63ac 100644
--- a/src/core/thread/Task.cpp
+++ b/src/core/thread/Task.cpp
@@ -29,6 +29,7 @@
#include "core/thread/Task.h"
#include <qobjectdefs.h>
+#include <qtmetamacros.h>
#include <boost/stacktrace.hpp>
#include <boost/uuid/uuid.hpp>
@@ -36,6 +37,8 @@
#include <boost/uuid/uuid_io.hpp>
#include <memory>
+#include "spdlog/spdlog.h"
+
namespace GpgFrontend::Thread {
class Task::Impl : public QObject {
@@ -186,37 +189,81 @@ class Task::Impl : public QObject {
try {
if (callback_) {
+ SPDLOG_DEBUG("task {} has a callback function", GetFullID());
if (callback_thread_ == QThread::currentThread()) {
SPDLOG_DEBUG("for task {}, the callback thread is the same thread",
GetFullID(), callback_thread_->currentThreadId());
+
callback_(rtn, data_object_);
+
+ // raise signal, announcing this task comes to an end
+ SPDLOG_DEBUG(
+ "for task {}, its life comes to an end in the same thread after "
+ "its callback executed.",
+ parent_->GetFullID());
+ emit parent_->SignalTaskEnd();
} else {
SPDLOG_DEBUG("for task {}, callback thread is a different thread: {}",
GetFullID(), callback_thread_->currentThreadId());
- if (!QMetaObject::invokeMethod(callback_thread_,
- [callback = callback_, rtn = rtn_,
- data_object = data_object_]() {
- callback(rtn, data_object);
- })) {
- SPDLOG_ERROR("task {} had failed to invoke callback", GetFullID());
+ if (!QMetaObject::invokeMethod(
+ callback_thread_,
+ [callback = callback_, rtn = rtn_, data_object = data_object_,
+ parent_ = this->parent_]() {
+ SPDLOG_DEBUG("calling callback of task {}",
+ parent_->GetFullID());
+ try {
+ callback(rtn, data_object);
+ } catch (...) {
+ SPDLOG_ERROR(
+ "unknown exception was caught when execute "
+ "callback of task {}",
+ parent_->GetFullID());
+ }
+ // raise signal, announcing this task comes to an end
+ SPDLOG_DEBUG(
+ "for task {}, its life comes to an end whether its "
+ "callback function fails or not.",
+ parent_->GetFullID());
+ emit parent_->SignalTaskEnd();
+ })) {
+ SPDLOG_ERROR(
+ "task {} had failed to invoke the callback function to target "
+ "thread",
+ GetFullID());
+ SPDLOG_DEBUG(
+ "for task {}, its life must come to an end now, although it "
+ "has something not done yet.",
+ GetFullID());
+ emit parent_->SignalTaskEnd();
}
}
+ } else {
+ // raise signal, announcing this task comes to an end
+ SPDLOG_DEBUG(
+ "for task {}, its life comes to an end without callback "
+ "peacefully.",
+ GetFullID());
+ emit parent_->SignalTaskEnd();
}
} catch (std::exception &e) {
SPDLOG_ERROR("exception was caught at task callback: {}", e.what());
SPDLOG_ERROR(
"stacktrace of the exception: {}",
boost::stacktrace::to_string(boost::stacktrace::stacktrace()));
+ // raise signal, announcing this task comes to an end
+ SPDLOG_DEBUG("for task {}, its life comes to an end at chaos.",
+ GetFullID());
+ emit parent_->SignalTaskEnd();
} catch (...) {
SPDLOG_ERROR("unknown exception was caught");
SPDLOG_ERROR(
"stacktrace of the exception: {}",
boost::stacktrace::to_string(boost::stacktrace::stacktrace()));
+ // raise signal, announcing this task comes to an end
+ SPDLOG_DEBUG("for task {}, its life comes to an end at unknown chaos.",
+ GetFullID());
+ emit parent_->SignalTaskEnd();
}
-
- // raise signal, announcing this task come to an end
- SPDLOG_DEBUG("for task {}, its life comes to an end.", GetFullID());
- emit parent_->SignalTaskEnd();
}
};
diff --git a/src/core/thread/TaskRunnerGetter.cpp b/src/core/thread/TaskRunnerGetter.cpp
index 70ac5226..ce7dbd32 100644
--- a/src/core/thread/TaskRunnerGetter.cpp
+++ b/src/core/thread/TaskRunnerGetter.cpp
@@ -28,21 +28,27 @@
#include "core/thread/TaskRunnerGetter.h"
-GpgFrontend::Thread::TaskRunnerGetter::TaskRunnerGetter(int channel)
+#include <memory>
+
+#include "thread/TaskRunner.h"
+
+namespace GpgFrontend::Thread {
+
+TaskRunnerGetter::TaskRunnerGetter(int channel)
: SingletonFunctionObject<TaskRunnerGetter>(channel) {}
-GpgFrontend::Thread::TaskRunner*
-GpgFrontend::Thread::TaskRunnerGetter::GetTaskRunner(
+TaskRunnerPtr GpgFrontend::Thread::TaskRunnerGetter::GetTaskRunner(
TaskRunnerType runner_type) {
while (true) {
auto it = task_runners_.find(runner_type);
if (it != task_runners_.end()) {
return it->second;
} else {
- auto runner = new TaskRunner();
+ auto runner = std::make_shared<TaskRunner>();
task_runners_[runner_type] = runner;
runner->Start();
continue;
}
}
-} \ No newline at end of file
+}
+} // namespace GpgFrontend::Thread \ No newline at end of file
diff --git a/src/core/thread/TaskRunnerGetter.h b/src/core/thread/TaskRunnerGetter.h
index f6500a5f..c76de036 100644
--- a/src/core/thread/TaskRunnerGetter.h
+++ b/src/core/thread/TaskRunnerGetter.h
@@ -34,6 +34,8 @@
namespace GpgFrontend::Thread {
+using TaskRunnerPtr = std::shared_ptr<TaskRunner>;
+
class GPGFRONTEND_CORE_EXPORT TaskRunnerGetter
: public GpgFrontend::SingletonFunctionObject<TaskRunnerGetter> {
public:
@@ -47,11 +49,11 @@ class GPGFRONTEND_CORE_EXPORT TaskRunnerGetter
TaskRunnerGetter(int channel = SingletonFunctionObject::GetDefaultChannel());
- TaskRunner *GetTaskRunner(
+ TaskRunnerPtr GetTaskRunner(
TaskRunnerType runner_type = kTaskRunnerType_Default);
private:
- std::map<TaskRunnerType, TaskRunner *> task_runners_;
+ std::map<TaskRunnerType, TaskRunnerPtr> task_runners_;
};
} // namespace GpgFrontend::Thread