aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/thread/TaskRunner.cpp
diff options
context:
space:
mode:
authorSaturn&Eric <[email protected]>2024-01-23 07:21:28 +0000
committerGitHub <[email protected]>2024-01-23 07:21:28 +0000
commit56acf161d439ce73eceaa145c40fe703bb2c3f02 (patch)
treea5d4790a6b2efc8786a3c0f74a07f5a8032d4e94 /src/core/thread/TaskRunner.cpp
parentfix: use more secure cdn links (diff)
parentfix: solve issues on detected gnupg path function and fix linking errors on w... (diff)
downloadGpgFrontend-56acf161d439ce73eceaa145c40fe703bb2c3f02.tar.gz
GpgFrontend-56acf161d439ce73eceaa145c40fe703bb2c3f02.zip
Merge pull request #126 from saturneric/dev/2.1.1/main
Develop 2.1.2.1
Diffstat (limited to 'src/core/thread/TaskRunner.cpp')
-rw-r--r--src/core/thread/TaskRunner.cpp212
1 files changed, 108 insertions, 104 deletions
diff --git a/src/core/thread/TaskRunner.cpp b/src/core/thread/TaskRunner.cpp
index 461d5fb5..8e381384 100644
--- a/src/core/thread/TaskRunner.cpp
+++ b/src/core/thread/TaskRunner.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -19,128 +19,132 @@
* The initial version of the source code is inherited from
* the gpg4usb project, which is under GPL-3.0-or-later.
*
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]><[email protected]> starting on May 12, 2021.
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#include "core/thread/TaskRunner.h"
#include "core/thread/Task.h"
-#include "spdlog/spdlog.h"
-GpgFrontend::Thread::TaskRunner::TaskRunner() = default;
+namespace GpgFrontend::Thread {
+
+class TaskRunner::Impl : public QThread {
+ public:
+ Impl() : QThread(nullptr) {}
-GpgFrontend::Thread::TaskRunner::~TaskRunner() = default;
+ void PostTask(Task* task) {
+ if (task == nullptr) {
+ GF_CORE_LOG_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);
+ task->moveToThread(this);
+
+ GF_CORE_LOG_TRACE("runner starts task: {} at thread: {}", task->GetFullID(),
+ this->currentThreadId());
+ task->SafelyRun();
}
- SPDLOG_TRACE("post task: {}", task->GetFullID());
+ auto RegisterTask(const QString& name, const Task::TaskRunnable& runnerable,
+ const Task::TaskCallback& cb, DataObjectPtr params)
+ -> Task::TaskHandler {
+ auto* raw_task = new Task(runnerable, name, std::move(params), cb);
+ raw_task->setParent(nullptr);
+ raw_task->moveToThread(this);
+
+ connect(raw_task, &Task::SignalRun, this, [this, raw_task]() {
+ pending_tasks_[raw_task->GetFullID()] = raw_task;
+ });
- task->setParent(nullptr);
- task->moveToThread(this);
+ connect(raw_task, &Task::SignalTaskEnd, this, [this, raw_task]() {
+ pending_tasks_.remove(raw_task->GetFullID());
+ });
- {
- std::lock_guard<std::mutex> lock(tasks_mutex_);
- tasks.push(task);
+ GF_CORE_LOG_TRACE("runner starts task: {} at thread: {}",
+ raw_task->GetFullID(), this->currentThreadId());
+
+ return Task::TaskHandler(raw_task);
}
- quit();
-}
-void GpgFrontend::Thread::TaskRunner::PostScheduleTask(Task* task,
- size_t seconds) {
- if (task == nullptr) return;
- // TODO
-}
+ void PostTask(const QString& name, const Task::TaskRunnable& runnerable,
+ const Task::TaskCallback& cb, DataObjectPtr params) {
+ PostTask(new Task(runnerable, name, std::move(params), cb));
+ }
-[[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 PostConcurrentTask(Task* task) {
+ if (task == nullptr) {
+ GF_CORE_LOG_ERROR("task posted is null");
+ return;
}
+
+ auto* concurrent_thread = new QThread(this);
+
+ task->setParent(nullptr);
+ task->moveToThread(concurrent_thread);
+
+ connect(task, &Task::SignalTaskEnd, concurrent_thread, &QThread::quit);
+ connect(concurrent_thread, &QThread::finished, concurrent_thread,
+ &QThread::deleteLater);
+
+ concurrent_thread->start();
+
+ GF_CORE_LOG_TRACE("runner starts task concurrenctly: {}",
+ task->GetFullID());
+ task->SafelyRun();
}
-}
-/**
- * @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 PostScheduleTask(Task* task, size_t seconds) {
+ if (task == nullptr) return;
+ // TODO
}
- SPDLOG_DEBUG("clean task {} done", task_uuid);
+ private:
+ QMap<QString, Task*> pending_tasks_;
+};
+
+TaskRunner::TaskRunner() : p_(SecureCreateUniqueObject<Impl>()) {}
+
+TaskRunner::~TaskRunner() {
+ if (p_->isRunning()) {
+ Stop();
+ }
+}
+
+void TaskRunner::PostTask(Task* task) { p_->PostTask(task); }
+
+void TaskRunner::PostTask(const QString& name, const Task::TaskRunnable& runner,
+ const Task::TaskCallback& cb, DataObjectPtr params) {
+ p_->PostTask(name, runner, cb, std::move(params));
+}
+
+void TaskRunner::PostConcurrentTask(Task* task) {
+ p_->PostConcurrentTask(task);
+}
+
+void TaskRunner::PostScheduleTask(Task* task, size_t seconds) {
+ p_->PostScheduleTask(task, seconds);
+}
+
+void TaskRunner::Start() { p_->start(); }
+
+void TaskRunner::Stop() {
+ p_->quit();
+ p_->wait();
+}
+
+auto TaskRunner::GetThread() -> QThread* { return p_.get(); }
+
+auto TaskRunner::IsRunning() -> bool { return p_->isRunning(); }
+
+auto TaskRunner::RegisterTask(const QString& name,
+ const Task::TaskRunnable& runnable,
+ const Task::TaskCallback& cb, DataObjectPtr p_pbj)
+ -> Task::TaskHandler {
+ return p_->RegisterTask(name, runnable, cb, p_pbj);
}
+} // namespace GpgFrontend::Thread