diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/function/gpg/GpgCommandExecutor.cpp | 59 | ||||
-rw-r--r-- | src/core/function/gpg/GpgCommandExecutor.h | 5 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyOpera.cpp | 1 | ||||
-rw-r--r-- | src/core/module/GlobalRegisterTable.cpp | 55 | ||||
-rw-r--r-- | src/core/thread/Task.cpp | 67 | ||||
-rw-r--r-- | src/core/thread/TaskRunnerGetter.cpp | 16 | ||||
-rw-r--r-- | src/core/thread/TaskRunnerGetter.h | 6 |
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 |