diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/module/GlobalModuleContext.cpp | 6 | ||||
-rw-r--r-- | src/core/module/ModuleManager.cpp | 2 | ||||
-rw-r--r-- | src/core/thread/Task.cpp | 120 | ||||
-rw-r--r-- | src/core/thread/Task.h | 3 | ||||
-rw-r--r-- | src/core/thread/TaskRunner.cpp | 157 | ||||
-rw-r--r-- | src/core/thread/TaskRunner.h | 28 | ||||
-rw-r--r-- | src/core/thread/TaskRunnerGetter.cpp | 2 | ||||
-rw-r--r-- | src/ui/GpgFrontendApplication.cpp | 8 | ||||
-rw-r--r-- | src/ui/main_window/MainWindow.cpp | 3 | ||||
-rw-r--r-- | src/ui/widgets/TextEdit.cpp | 1 |
10 files changed, 120 insertions, 210 deletions
diff --git a/src/core/module/GlobalModuleContext.cpp b/src/core/module/GlobalModuleContext.cpp index 7e5f8f00..10c3e549 100644 --- a/src/core/module/GlobalModuleContext.cpp +++ b/src/core/module/GlobalModuleContext.cpp @@ -119,10 +119,10 @@ class GlobalModuleContext::Impl { register_info.module = module; register_info.channel = acquire_new_unique_channel(); register_info.task_runner = std::make_shared<Thread::TaskRunner>(); - register_info.task_runner->start(); + register_info.task_runner->Start(); // move module to its task runner' thread - register_info.module->moveToThread(register_info.task_runner.get()); + register_info.module->moveToThread(register_info.task_runner->GetThread()); // Register the module with its identifier. module_register_table_[module->GetModuleIdentifier()] = @@ -239,7 +239,7 @@ class GlobalModuleContext::Impl { "module {} is listening to event {}, activate state: {}, task runner " "running state: {}", module_info->module->GetModuleIdentifier(), event->GetIdentifier(), - module_info->activate, module_info->task_runner->isRunning()); + module_info->activate, module_info->task_runner->IsRunning()); // Check if the module is activated if (!module_info->activate) continue; diff --git a/src/core/module/ModuleManager.cpp b/src/core/module/ModuleManager.cpp index dc31072b..b9e73721 100644 --- a/src/core/module/ModuleManager.cpp +++ b/src/core/module/ModuleManager.cpp @@ -41,7 +41,7 @@ class ModuleManager::Impl { Impl() : task_runner_(std::make_shared<Thread::TaskRunner>()), gpc_(std::make_shared<GlobalModuleContext>(task_runner_)) { - task_runner_->start(); + task_runner_->Start(); } void RegisterModule(ModulePtr module) { diff --git a/src/core/thread/Task.cpp b/src/core/thread/Task.cpp index 8793ea2d..031dc4c7 100644 --- a/src/core/thread/Task.cpp +++ b/src/core/thread/Task.cpp @@ -34,6 +34,8 @@ #include <boost/uuid/uuid_io.hpp> #include <memory> +#include "spdlog/spdlog.h" + namespace GpgFrontend::Thread { class Task::Impl : public QObject { @@ -48,7 +50,8 @@ class Task::Impl : public QObject { Impl(Task *parent, TaskRunnable runnable, std::string name, DataObjectPtr data_object, bool sequency) - : parent_(parent), + : QObject(parent), + parent_(parent), uuid_(generate_uuid()), name_(name), runnable_(std::move(runnable)), @@ -63,7 +66,8 @@ class Task::Impl : public QObject { Impl(Task *parent, TaskRunnable runnable, std::string name, DataObjectPtr data_object, TaskCallback callback, bool sequency) - : parent_(parent), + : QObject(parent), + parent_(parent), uuid_(generate_uuid()), name_(name), runnable_(std::move(runnable)), @@ -71,10 +75,10 @@ class Task::Impl : public QObject { callback_thread_(QThread::currentThread()), data_object_(data_object), sequency_(sequency) { - init(); SPDLOG_TRACE( "task {} created with runnable and callback, callback_thread_: {}", GetFullID(), static_cast<void *>(callback_thread_)); + init(); } ~Impl() { SPDLOG_TRACE("task {} destroyed", GetFullID()); } @@ -91,6 +95,8 @@ class Task::Impl : public QObject { bool GetSequency() const { return sequency_; } void Run() { + SPDLOG_DEBUG("task {} is using default runnable and callback mode", + GetFullID()); if (runnable_) { SetRTN(runnable_(data_object_)); } else { @@ -114,62 +120,29 @@ class Task::Impl : public QObject { */ void SetRTN(int rtn) { this->rtn_ = rtn; } + private slots: + /** * @brief * */ - void DoRunning() { - SPDLOG_TRACE("task {} starting", GetFullID()); - - // build runnable package for running - auto runnable_package = [this, id = GetFullID()]() { - SPDLOG_DEBUG("task {} runnable start runing", id); - - try { - // Run() will set rtn by itself - parent_->Run(); - } catch (std::exception &e) { - SPDLOG_ERROR("exception caught at task: {}", e.what()); - SPDLOG_ERROR( - "exception stacktrace: {}", - boost::stacktrace::to_string(boost::stacktrace::stacktrace())); - } - - // raise signal to anounce after runnable returned - if (run_callback_after_runnable_finished_) - emit parent_->SignalTaskRunnableEnd(rtn_); - }; - - if (thread() != QThread::currentThread()) { - SPDLOG_DEBUG("task running thread is not object living thread"); - // if running sequently - if (sequency_) { - // running in another thread, blocking until returned - if (!QMetaObject::invokeMethod(thread(), runnable_package, - Qt::BlockingQueuedConnection)) { - SPDLOG_ERROR("qt invoke method failed"); - } - } else { - // running in another thread, non-blocking - if (!QMetaObject::invokeMethod(thread(), runnable_package)) { - SPDLOG_ERROR("qt invoke method failed"); - } - } - } else { - if (!QMetaObject::invokeMethod(this, runnable_package)) { - SPDLOG_ERROR("qt invoke method failed"); - } + void slot_run() { + try { + SPDLOG_TRACE("task {} is starting...", GetFullID()); + // Run() will set rtn by itself + parent_->Run(); + SPDLOG_TRACE("task {} was end.", GetFullID()); + } catch (std::exception &e) { + SPDLOG_ERROR("exception was caught at task: {}", e.what()); + SPDLOG_ERROR( + "stacktrace of the exception: {}", + boost::stacktrace::to_string(boost::stacktrace::stacktrace())); } + // raise signal to anounce after runnable returned + if (run_callback_after_runnable_finished_) + emit parent_->SignalTaskRunnableEnd(rtn_); } - public slots: - - /** - * @brief - * - */ - void SlotRun() { DoRunning(); } - private: Task *const parent_; const std::string uuid_; @@ -183,6 +156,8 @@ class Task::Impl : public QObject { DataObjectPtr data_object_ = nullptr; ///< void init() { + connect(parent_, &Task::SignalRun, this, &Task::Impl::slot_run); + // after runnable finished, running callback connect(parent_, &Task::SignalTaskRunnableEnd, this, &Impl::slot_task_run_callback); @@ -211,42 +186,35 @@ class Task::Impl : public QObject { try { if (callback_) { if (callback_thread_ == QThread::currentThread()) { - SPDLOG_DEBUG("callback thread is the same thread"); + SPDLOG_DEBUG("for task {}, the callback thread is the same thread", + GetFullID(), callback_thread_->currentThreadId()); + callback_(rtn, data_object_); + } 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_, this]() { + data_object = data_object_]() { callback(rtn, data_object); - // do cleaning work - emit parent_->SignalTaskEnd(); })) { - SPDLOG_ERROR("failed to invoke callback"); - } - // just finished, let callack thread to raise SignalTaskEnd - return; - } else { - // waiting for callback to finish - if (!QMetaObject::invokeMethod( - callback_thread_, - [callback = callback_, rtn = rtn_, - data_object = data_object_]() { - callback(rtn, data_object); - }, - Qt::BlockingQueuedConnection)) { - SPDLOG_ERROR("failed to invoke callback"); + SPDLOG_ERROR("task {} had failed to invoke callback", GetFullID()); } } } } catch (std::exception &e) { - SPDLOG_ERROR("exception caught at task callback: {}", e.what()); + SPDLOG_ERROR("exception was caught at task callback: {}", e.what()); SPDLOG_ERROR( - "exception stacktrace: {}", + "stacktrace of the exception: {}", boost::stacktrace::to_string(boost::stacktrace::stacktrace())); } catch (...) { - SPDLOG_ERROR("unknown exception caught"); + SPDLOG_ERROR("unknown exception was caught"); + SPDLOG_ERROR( + "stacktrace of the exception: {}", + boost::stacktrace::to_string(boost::stacktrace::stacktrace())); } // raise signal, announcing this task come to an end - SPDLOG_DEBUG("task {}, starting calling signal SignalTaskEnd", GetFullID()); + SPDLOG_DEBUG("for task {}, its life comes to an end.", GetFullID()); emit parent_->SignalTaskEnd(); } }; @@ -281,11 +249,11 @@ void Task::HoldOnLifeCycle(bool hold_on) { p_->HoldOnLifeCycle(hold_on); } void Task::SetRTN(int rtn) { p_->SetRTN(rtn); } -void Task::SlotRun() { p_->SlotRun(); } +void Task::SlotRun() { emit SignalRun(); } void Task::Run() { p_->Run(); } -void Task::run() { p_->DoRunning(); } +void Task::run() { emit SignalRun(); } } // namespace GpgFrontend::Thread diff --git a/src/core/thread/Task.h b/src/core/thread/Task.h index 8f3a76f9..388b5a35 100644 --- a/src/core/thread/Task.h +++ b/src/core/thread/Task.h @@ -113,6 +113,9 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { void SlotRun(); signals: + + void SignalRun(); + /** * @brief announce runnable finished * diff --git a/src/core/thread/TaskRunner.cpp b/src/core/thread/TaskRunner.cpp index 35ac561e..6eed7a89 100644 --- a/src/core/thread/TaskRunner.cpp +++ b/src/core/thread/TaskRunner.cpp @@ -28,121 +28,72 @@ #include "core/thread/TaskRunner.h" +#include <qobjectdefs.h> +#include <qthread.h> + +#include <memory> + #include "core/thread/Task.h" #include "spdlog/spdlog.h" -GpgFrontend::Thread::TaskRunner::TaskRunner() = default; +namespace GpgFrontend::Thread { -GpgFrontend::Thread::TaskRunner::~TaskRunner() = default; +class TaskRunner::Impl : public QThread { + public: + void PostTask(Task* task) { + if (task == nullptr) { + SPDLOG_ERROR("task posted is null"); + return; + } -void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) { - if (task == nullptr) { - SPDLOG_ERROR("task posted is null"); - return; + task->setParent(nullptr); + connect(task, &Task::SignalTaskEnd, task, &Task::deleteLater); + + if (task->GetSequency()) { + SPDLOG_TRACE("post task: {}, sequency mode: {}", task->GetFullID(), + task->GetSequency()); + task->moveToThread(this); + } else { + // if it need to run concurrently, we should create a new thread to + // run it. + auto* concurrent_thread = new QThread(this); + + connect(task, &Task::SignalTaskEnd, concurrent_thread, &QThread::quit); + // concurrent thread is responsible for deleting the task + connect(concurrent_thread, &QThread::finished, task, &Task::deleteLater); + // concurrent thread is responsible for self deleting + connect(concurrent_thread, &QThread::finished, concurrent_thread, + &QThread::deleteLater); + + // start thread + concurrent_thread->start(); + task->moveToThread(concurrent_thread); + } + emit task->SignalRun(); } - SPDLOG_TRACE("post task: {}", task->GetFullID()); + void PostScheduleTask(Task* task, size_t seconds) { + if (task == nullptr) return; + // TODO + } +}; - task->setParent(nullptr); - task->moveToThread(this); +GpgFrontend::Thread::TaskRunner::TaskRunner() : p_(std::make_unique<Impl>()) {} - { - std::lock_guard<std::mutex> lock(tasks_mutex_); - tasks.push(task); - } - quit(); -} +GpgFrontend::Thread::TaskRunner::~TaskRunner() = default; -void GpgFrontend::Thread::TaskRunner::PostScheduleTask(Task* task, - size_t seconds) { - if (task == nullptr) return; - // TODO +void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) { + p_->PostTask(task); } -[[noreturn]] void GpgFrontend::Thread::TaskRunner::run() { - SPDLOG_TRACE("task runner runing, thread id: {}", QThread::currentThreadId()); - while (true) { - if (tasks.empty()) { - SPDLOG_TRACE("no tasks to run, trapping into event loop..."); - exec(); - } else { - SPDLOG_TRACE("start to run task(s), queue size: {}", tasks.size()); - - Task* task = nullptr; - { - std::lock_guard<std::mutex> lock(tasks_mutex_); - task = std::move(tasks.front()); - tasks.pop(); - pending_tasks_.insert({task->GetUUID(), task}); - } - - if (task != nullptr) { - try { - // triger - SPDLOG_TRACE("running task {}, sequency: {}", task->GetFullID(), - task->GetSequency()); - - // when a signal SignalTaskEnd raise, do unregister work - connect(task, &Task::SignalTaskEnd, this, [this, task]() { - unregister_finished_task(task->GetUUID()); - }); - - if (!task->GetSequency()) { - // if it need to run concurrently, we should create a new thread to - // run it. - auto* concurrent_thread = new QThread(nullptr); - task->setParent(nullptr); - task->moveToThread(concurrent_thread); - // start thread - concurrent_thread->start(); - - connect(task, &Task::SignalTaskEnd, concurrent_thread, - &QThread::quit); - // concurrent thread is responsible for deleting the task - connect(concurrent_thread, &QThread::finished, task, - &Task::deleteLater); - } - - // run the task - task->run(); - } catch (const std::exception& e) { - SPDLOG_ERROR("task runner: exception in task {}, exception: {}", - task->GetFullID(), e.what()); - // if any exception caught, destroy the task, remove the task from the - // pending tasks - unregister_finished_task(task->GetUUID()); - } catch (...) { - SPDLOG_ERROR("task runner: unknown exception in task: {}", - task->GetFullID()); - // if any exception caught, destroy the task, remove the task from the - // pending tasks - unregister_finished_task(task->GetUUID()); - } - } - } - } +void TaskRunner::PostScheduleTask(Task* task, size_t seconds) { + p_->PostScheduleTask(task, seconds); } -/** - * @brief - * - */ -void GpgFrontend::Thread::TaskRunner::unregister_finished_task( - std::string task_uuid) { - SPDLOG_DEBUG("cleaning task {}", task_uuid); - // search in map - auto pending_task = pending_tasks_.find(task_uuid); - if (pending_task == pending_tasks_.end()) { - SPDLOG_ERROR("cannot find task in pending list: {}", task_uuid); - return; - } else { - std::lock_guard<std::mutex> lock(tasks_mutex_); - // if thread runs sequenctly, that means the thread is living in this - // thread, so we can delete it. Or, its living thread need to delete it. - if (pending_task->second->GetSequency()) - pending_task->second->deleteLater(); - pending_tasks_.erase(pending_task); - } +void TaskRunner::Start() { p_->start(); } - SPDLOG_DEBUG("clean task {} done", task_uuid); -} +QThread* TaskRunner::GetThread() { return p_.get(); } + +bool TaskRunner::IsRunning() { return p_->isRunning(); } + +} // namespace GpgFrontend::Thread diff --git a/src/core/thread/TaskRunner.h b/src/core/thread/TaskRunner.h index f388a4f6..25187178 100644 --- a/src/core/thread/TaskRunner.h +++ b/src/core/thread/TaskRunner.h @@ -29,17 +29,13 @@ #ifndef GPGFRONTEND_TASKRUNNER_H #define GPGFRONTEND_TASKRUNNER_H -#include <cstddef> -#include <mutex> -#include <queue> - #include "core/GpgFrontendCore.h" namespace GpgFrontend::Thread { class Task; -class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread { +class GPGFRONTEND_CORE_EXPORT TaskRunner : public QObject { Q_OBJECT public: /** @@ -54,11 +50,11 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread { */ virtual ~TaskRunner() override; - /** - * @brief - * - */ - [[noreturn]] void run() override; + void Start(); + + QThread* GetThread(); + + bool IsRunning(); public slots: @@ -78,16 +74,8 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread { void PostScheduleTask(Task* task, size_t seconds); private: - 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 - - /** - * @brief - * - */ - void unregister_finished_task(std::string); + class Impl; + std::unique_ptr<Impl> p_; }; } // namespace GpgFrontend::Thread diff --git a/src/core/thread/TaskRunnerGetter.cpp b/src/core/thread/TaskRunnerGetter.cpp index 9288c2cd..70ac5226 100644 --- a/src/core/thread/TaskRunnerGetter.cpp +++ b/src/core/thread/TaskRunnerGetter.cpp @@ -41,7 +41,7 @@ GpgFrontend::Thread::TaskRunnerGetter::GetTaskRunner( } else { auto runner = new TaskRunner(); task_runners_[runner_type] = runner; - runner->start(); + runner->Start(); continue; } } diff --git a/src/ui/GpgFrontendApplication.cpp b/src/ui/GpgFrontendApplication.cpp index 6f80f534..21932f44 100644 --- a/src/ui/GpgFrontendApplication.cpp +++ b/src/ui/GpgFrontendApplication.cpp @@ -77,8 +77,8 @@ bool GpgFrontendApplication::notify(QObject *receiver, QEvent *event) { try { app_done = QApplication::notify(receiver, event); } catch (const std::exception &ex) { - SPDLOG_ERROR("exception caught in notify: {}", ex.what()); - SPDLOG_ERROR("exception stacktrace: {}", + SPDLOG_ERROR("exception was caught in notify: {}", ex.what()); + SPDLOG_ERROR("stacktrace of the exception: {}", boost::stacktrace::to_string(boost::stacktrace::stacktrace())); QMessageBox::information(nullptr, _("Standard Exception Thrown"), _("Oops, an standard exception was thrown " @@ -87,7 +87,9 @@ bool GpgFrontendApplication::notify(QObject *receiver, QEvent *event) { "be the negligence of the programmer, " "please report this problem if you can.")); } catch (...) { - SPDLOG_ERROR("unknown exception caught in notify"); + SPDLOG_ERROR("unknown exception was caught in notify"); + SPDLOG_ERROR("stacktrace of the exception: {}", + boost::stacktrace::to_string(boost::stacktrace::stacktrace())); QMessageBox::information( nullptr, _("Unhandled Exception Thrown"), _("Oops, an unhandled exception was thrown " diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp index eeb1971c..dbca1f55 100644 --- a/src/ui/main_window/MainWindow.cpp +++ b/src/ui/main_window/MainWindow.cpp @@ -34,7 +34,6 @@ #include "core/function/gpg/GpgAdvancedOperator.h" #include "core/module/ModuleManager.h" #include "main_window/GeneralMainWindow.h" -#include "nlohmann/json_fwd.hpp" #include "spdlog/spdlog.h" #include "ui/SignalStation.h" #include "ui/UserInterfaceUtils.h" @@ -144,7 +143,7 @@ void MainWindow::Init() noexcept { slot_start_wizard(); } - emit SignalLoaded(); + emit SignalLoaded(); Module::TriggerEvent("APPLICATION_LOADED"); // if not prohibit update checking diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp index f44c076c..fff7ca1b 100644 --- a/src/ui/widgets/TextEdit.cpp +++ b/src/ui/widgets/TextEdit.cpp @@ -36,7 +36,6 @@ #include "core/function/CacheManager.h" #include "core/function/GlobalSettingStation.h" -#include "nlohmann/json_fwd.hpp" #include "spdlog/spdlog.h" namespace GpgFrontend::UI { |