aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/module/GlobalModuleContext.cpp6
-rw-r--r--src/core/module/ModuleManager.cpp2
-rw-r--r--src/core/thread/Task.cpp120
-rw-r--r--src/core/thread/Task.h3
-rw-r--r--src/core/thread/TaskRunner.cpp157
-rw-r--r--src/core/thread/TaskRunner.h28
-rw-r--r--src/core/thread/TaskRunnerGetter.cpp2
-rw-r--r--src/ui/GpgFrontendApplication.cpp8
-rw-r--r--src/ui/main_window/MainWindow.cpp3
-rw-r--r--src/ui/widgets/TextEdit.cpp1
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 {