aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/thread
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/thread')
-rw-r--r--src/core/thread/CtxCheckTask.cpp54
-rw-r--r--src/core/thread/CtxCheckTask.h63
-rw-r--r--src/core/thread/FileReadTask.cpp60
-rw-r--r--src/core/thread/FileReadTask.h22
-rw-r--r--src/core/thread/Task.cpp370
-rw-r--r--src/core/thread/Task.h223
-rw-r--r--src/core/thread/TaskRunner.cpp212
-rw-r--r--src/core/thread/TaskRunner.h83
-rw-r--r--src/core/thread/TaskRunnerGetter.cpp44
-rw-r--r--src/core/thread/TaskRunnerGetter.h32
-rw-r--r--src/core/thread/ThreadingModel.h9
11 files changed, 507 insertions, 665 deletions
diff --git a/src/core/thread/CtxCheckTask.cpp b/src/core/thread/CtxCheckTask.cpp
deleted file mode 100644
index 9735fcaa..00000000
--- a/src/core/thread/CtxCheckTask.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Copyright (C) 2021 Saturneric
- *
- * This file is part of GpgFrontend.
- *
- * GpgFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GpgFrontend is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
- *
- * 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.
- *
- */
-
-#include "core/thread/CtxCheckTask.h"
-
-#include "core/GpgContext.h"
-#include "core/GpgCoreInit.h"
-#include "core/common/CoreCommonUtil.h"
-#include "core/function/gpg/GpgKeyGetter.h"
-#include "thread/Task.h"
-
-GpgFrontend::Thread::CtxCheckTask::CtxCheckTask() : Task("ctx_check_task") {
- connect(this, &CtxCheckTask::SignalGnupgNotInstall,
- CoreCommonUtil::GetInstance(),
- &CoreCommonUtil::SignalGnupgNotInstall);
-}
-
-void GpgFrontend::Thread::CtxCheckTask::Run() {
- // Init GpgFrontend Core
- init_gpgfrontend_core();
-
- // Create & Check Gnupg Context Status
- if (!GpgContext::GetInstance().good()) {
- emit SignalGnupgNotInstall();
- }
- // Try flushing key cache
- else
- GpgFrontend::GpgKeyGetter::GetInstance().FlushKeyCache();
-
- SPDLOG_DEBUG("ctx check task runnable done");
-}
diff --git a/src/core/thread/CtxCheckTask.h b/src/core/thread/CtxCheckTask.h
deleted file mode 100644
index 06ddfd82..00000000
--- a/src/core/thread/CtxCheckTask.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Copyright (C) 2021 Saturneric
- *
- * This file is part of GpgFrontend.
- *
- * GpgFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GpgFrontend is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
- *
- * 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.
- *
- */
-
-#ifndef GPGFRONTEND_CTXCHECKTRHEAD_H
-#define GPGFRONTEND_CTXCHECKTRHEAD_H
-
-#include "core/GpgFrontendCore.h"
-#include "core/thread/Task.h"
-
-namespace GpgFrontend::Thread {
-/**
- * @brief
- *
- */
-class GPGFRONTEND_CORE_EXPORT CtxCheckTask : public Task {
- Q_OBJECT
- public:
- /**
- * @brief Construct a new Ctx Check Thread object
- *
- */
- CtxCheckTask();
-
- signals:
- /**
- * @brief
- *
- */
- void SignalGnupgNotInstall();
-
- protected:
- /**
- * @brief
- *
- */
- void Run() override;
-};
-} // namespace GpgFrontend::Thread
-
-#endif // GPGFRONTEND_CTXCHECKTRHEAD_H
diff --git a/src/core/thread/FileReadTask.cpp b/src/core/thread/FileReadTask.cpp
index 73954d28..49a3f540 100644
--- a/src/core/thread/FileReadTask.cpp
+++ b/src/core/thread/FileReadTask.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -19,8 +19,10 @@
* 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
*
*/
@@ -28,58 +30,52 @@
namespace GpgFrontend::UI {
-FileReadTask::FileReadTask(std::string path) : Task("file_read_task") {
- connect(this, &FileReadTask::SignalFileBytesReadNext, this,
- &FileReadTask::read_bytes);
+constexpr size_t kBufferSize = 8192;
-#ifdef WINDOWS
- std::filesystem::path read_file_path(
- QString::fromStdString(path).toStdU16String());
-#else
- std::filesystem::path read_file_path(
- QString::fromStdString(path).toStdString());
-#endif
- read_file_path_ = read_file_path;
+FileReadTask::FileReadTask(QString path)
+ : Task("file_read_task"), read_file_path_(std::move(path)) {
+ HoldOnLifeCycle(true);
+ connect(this, &FileReadTask::SignalFileBytesReadNext, this,
+ &FileReadTask::slot_read_bytes);
}
-void FileReadTask::Run() {
- SetFinishAfterRun(false);
-
- if (is_regular_file(read_file_path_)) {
- SPDLOG_DEBUG("read open file: {}", read_file_path_.u8string());
+auto FileReadTask::Run() -> int {
+ if (QFileInfo(read_file_path_).isFile()) {
+ GF_CORE_LOG_DEBUG("read open file: {}", read_file_path_);
- target_file_.setFileName(
- QString::fromStdString(read_file_path_.u8string()));
+ target_file_.setFileName(read_file_path_);
target_file_.open(QIODevice::ReadOnly);
if (!(target_file_.isOpen() && target_file_.isReadable())) {
- SPDLOG_ERROR("file not open or not readable");
+ GF_CORE_LOG_ERROR("file not open or not readable");
if (target_file_.isOpen()) target_file_.close();
- return;
+ return -1;
}
- SPDLOG_DEBUG("started reading: {}", read_file_path_.u8string());
- read_bytes();
+ GF_CORE_LOG_DEBUG("started reading: {}", read_file_path_);
+ slot_read_bytes();
} else {
emit SignalFileBytesReadEnd();
}
+ return 0;
}
-void FileReadTask::read_bytes() {
+void FileReadTask::slot_read_bytes() {
QByteArray read_buffer;
- if (!target_file_.atEnd() &&
- (read_buffer = target_file_.read(buffer_size_)).size() > 0) {
- SPDLOG_DEBUG("read bytes: {}", read_buffer.size());
+ if (QByteArray read_buffer;
+ !target_file_.atEnd() &&
+ (read_buffer = target_file_.read(kBufferSize)).size() > 0) {
+ GF_CORE_LOG_DEBUG("io thread read bytes: {}", read_buffer.size());
emit SignalFileBytesRead(std::move(read_buffer));
} else {
- SPDLOG_DEBUG("read bytes end");
+ GF_CORE_LOG_DEBUG("io thread read bytes end");
emit SignalFileBytesReadEnd();
// announce finish task
- emit SignalTaskRunnableEnd(0);
+ emit SignalTaskShouldEnd(0);
}
}
FileReadTask::~FileReadTask() {
- SPDLOG_DEBUG("close file: {}", read_file_path_.u8string());
+ GF_CORE_LOG_DEBUG("close file: {}", read_file_path_);
if (target_file_.isOpen()) target_file_.close();
}
diff --git a/src/core/thread/FileReadTask.h b/src/core/thread/FileReadTask.h
index d4e61cbe..22be33ef 100644
--- a/src/core/thread/FileReadTask.h
+++ b/src/core/thread/FileReadTask.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -19,13 +19,14 @@
* 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
*
*/
-#ifndef GPGFRONTEND_FILEREADTHREAD_H
-#define GPGFRONTEND_FILEREADTHREAD_H
+#pragma once
#include "core/GpgFrontendCore.h"
#include "core/thread/Task.h"
@@ -39,11 +40,11 @@ namespace GpgFrontend::UI {
class GPGFRONTEND_CORE_EXPORT FileReadTask : public GpgFrontend::Thread::Task {
Q_OBJECT
public:
- explicit FileReadTask(std::string path);
+ explicit FileReadTask(QString path);
virtual ~FileReadTask() override;
- void Run() override;
+ int Run() override;
signals:
void SignalFileBytesRead(QByteArray bytes);
@@ -51,15 +52,12 @@ class GPGFRONTEND_CORE_EXPORT FileReadTask : public GpgFrontend::Thread::Task {
void SignalFileBytesReadNext();
private:
- std::filesystem::path read_file_path_;
+ QString read_file_path_;
QFile target_file_;
- const size_t buffer_size_ = 4096;
QEventLoop looper;
private slots:
- void read_bytes();
+ void slot_read_bytes();
};
} // namespace GpgFrontend::UI
-
-#endif // GPGFRONTEND_FILEREADTHREAD_H
diff --git a/src/core/thread/Task.cpp b/src/core/thread/Task.cpp
index 7173b69e..dc0cfe94 100644
--- a/src/core/thread/Task.cpp
+++ b/src/core/thread/Task.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -19,209 +19,237 @@
* 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/Task.h"
-#include <boost/uuid/uuid.hpp>
-#include <boost/uuid/uuid_generators.hpp>
-#include <boost/uuid/uuid_io.hpp>
-#include <functional>
-#include <string>
-#include <utility>
+#include <qscopedpointer.h>
-#include "core/thread/TaskRunner.h"
+#include "utils/MemoryUtils.h"
-const std::string GpgFrontend::Thread::Task::DEFAULT_TASK_NAME = "default-task";
+namespace GpgFrontend::Thread {
-GpgFrontend::Thread::Task::Task(std::string name)
- : uuid_(generate_uuid()), name_(name) {
- SPDLOG_TRACE("task {}/ created", GetFullID());
- init();
-}
+class Task::Impl {
+ public:
+ Impl(Task *parent, QString name)
+ : parent_(parent), uuid_(generate_uuid()), name_(std::move(name)) {
+ GF_CORE_LOG_TRACE("task {} created", GetFullID());
+ init();
+ }
-GpgFrontend::Thread::Task::Task(TaskRunnable runnable, std::string name,
- DataObjectPtr data_object, bool sequency)
- : uuid_(generate_uuid()),
- name_(name),
- runnable_(std::move(runnable)),
- callback_(std::move([](int, const std::shared_ptr<DataObject> &) {})),
- callback_thread_(QThread::currentThread()),
- data_object_(data_object),
- sequency_(sequency) {
- SPDLOG_TRACE("task {} created with runnable, callback_thread_: {}",
- GetFullID(), static_cast<void *>(callback_thread_));
- init();
-}
+ Impl(Task *parent, TaskRunnable runnable, QString name,
+ DataObjectPtr data_object)
+ : parent_(parent),
+ uuid_(generate_uuid()),
+ name_(std::move(name)),
+ runnable_(std::move(runnable)),
+ callback_([](int, const DataObjectPtr &) {}),
+ callback_thread_(QThread::currentThread()),
+ data_object_(std::move(data_object)) {
+ GF_CORE_LOG_TRACE("task {} created with runnable, callback_thread_: {}",
+ GetFullID(), static_cast<void *>(callback_thread_));
+ init();
+ }
-GpgFrontend::Thread::Task::Task(TaskRunnable runnable, std::string name,
- DataObjectPtr data_object,
- TaskCallback callback, bool sequency)
- : uuid_(generate_uuid()),
- name_(name),
- runnable_(std::move(runnable)),
- callback_(std::move(callback)),
- 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_));
-}
+ Impl(Task *parent, TaskRunnable runnable, QString name,
+ DataObjectPtr data_object, TaskCallback callback)
+ : parent_(parent),
+ uuid_(generate_uuid()),
+ name_(std::move(name)),
+ runnable_(std::move(runnable)),
+ callback_(std::move(callback)),
+ callback_thread_(QThread::currentThread()),
+ data_object_(std::move(data_object)) {
+ GF_CORE_LOG_TRACE(
+ "task {} created with runnable and callback, callback_thread_: {}",
+ GetFullID(), static_cast<void *>(callback_thread_));
+ init();
+ }
-GpgFrontend::Thread::Task::~Task() {
- SPDLOG_TRACE("task {} destroyed", GetFullID());
-}
+ ~Impl() { GF_CORE_LOG_TRACE("task {} destroyed", GetFullID()); }
+
+ /**
+ * @brief
+ *
+ * @return QString
+ */
+ [[nodiscard]] auto GetFullID() const -> QString {
+ return uuid_ + "/" + name_;
+ }
+
+ /**
+ * @brief
+ *
+ * @return QString
+ */
+ [[nodiscard]] auto GetUUID() const -> QString { return uuid_; }
+
+ /**
+ * @brief
+ *
+ * @return int
+ */
+ auto Run() -> int {
+ GF_CORE_LOG_TRACE("task {} is in classical runnable and callback mode",
+ GetFullID());
+
+ if (runnable_) return runnable_(data_object_);
+
+ GF_CORE_LOG_WARN("no runnable in task, do callback operation, task: {}",
+ GetFullID());
+ return 0;
+ }
+
+ /**
+ * @brief Set the Finish After Run object
+ *
+ * @param finish_after_run
+ */
+ void HoldOnLifeCycle(bool hold_on) { parent_->setAutoDelete(!hold_on); }
+
+ /**
+ * @brief
+ *
+ * @param rtn
+ */
+ void SetRTN(int rtn) { this->rtn_ = rtn; }
+
+ /**
+ * @brief
+ *
+ * @return auto
+ */
+ [[nodiscard]] auto GetRTN() const { return this->rtn_; }
+
+ private:
+ Task *const parent_;
+ const QString uuid_;
+ const QString name_;
+ TaskRunnable runnable_; ///<
+ TaskCallback callback_; ///<
+ int rtn_ = -99; ///<
+ QThread *callback_thread_ = nullptr; ///<
+ DataObjectPtr data_object_ = nullptr; ///<
+
+ void init() {
+ GF_CORE_LOG_TRACE("task {} created, parent: {}, impl: {}", name_,
+ static_cast<void *>(parent_), static_cast<void *>(this));
+
+ //
+ HoldOnLifeCycle(false);
+
+ //
+ connect(parent_, &Task::SignalRun, parent_, &Task::slot_exception_safe_run);
+
+ auto *callback_thread = callback_thread_ != nullptr
+ ? callback_thread_
+ : QCoreApplication::instance()->thread();
+ //
+ connect(parent_, &Task::SignalTaskShouldEnd, callback_thread,
+ [this](int rtn) {
+ // set task returning code
+ SetRTN(rtn);
+ try {
+ if (callback_) {
+ GF_CORE_LOG_TRACE(
+ "task callback {} is starting with runnerable rtn: {}",
+ GetFullID(), rtn);
+
+ callback_(rtn_, data_object_);
+ GF_CORE_LOG_TRACE("task callback {} finished, rtn: {}",
+ GetFullID(), rtn);
+ }
+ } catch (...) {
+ GF_CORE_LOG_ERROR("task {} callback caught exception, rtn: {}",
+ GetFullID(), rtn);
+ }
+ emit parent_->SignalTaskEnd();
+ });
+
+ //
+ connect(parent_, &Task::SignalTaskEnd, parent_, &Task::deleteLater);
+ }
+
+ /**
+ * @brief
+ *
+ * @return QString
+ */
+ static auto generate_uuid() -> QString {
+ return QUuid::createUuid().toString();
+ }
+};
+
+Task::Task(QString name) : p_(new Impl(this, name)) {}
+
+Task::Task(TaskRunnable runnable, QString name, DataObjectPtr data_object)
+ : p_(SecureCreateUniqueObject<Impl>(this, runnable, name, data_object)) {}
+
+Task::Task(TaskRunnable runnable, QString name, DataObjectPtr data_object,
+ TaskCallback callback)
+ : p_(SecureCreateUniqueObject<Impl>(this, runnable, name, data_object,
+ callback)) {}
+
+Task::~Task() = default;
/**
* @brief
*
- * @return std::string
+ * @return QString
*/
-std::string GpgFrontend::Thread::Task::GetFullID() const {
- return uuid_ + "/" + name_;
-}
-
-std::string GpgFrontend::Thread::Task::GetUUID() const { return uuid_; }
+QString Task::GetFullID() const { return p_->GetFullID(); }
-bool GpgFrontend::Thread::Task::GetSequency() const { return sequency_; }
+QString Task::GetUUID() const { return p_->GetUUID(); }
-void GpgFrontend::Thread::Task::SetFinishAfterRun(
- bool run_callback_after_runnable_finished) {
- this->run_callback_after_runnable_finished_ =
- run_callback_after_runnable_finished;
-}
+void Task::HoldOnLifeCycle(bool hold_on) { p_->HoldOnLifeCycle(hold_on); }
-void GpgFrontend::Thread::Task::SetRTN(int rtn) { this->rtn_ = rtn; }
-
-void GpgFrontend::Thread::Task::init() {
- // after runnable finished, running callback
- connect(this, &Task::SignalTaskRunnableEnd, this,
- &Task::slot_task_run_callback);
-}
+void Task::setRTN(int rtn) { p_->SetRTN(rtn); }
-void GpgFrontend::Thread::Task::slot_task_run_callback(int rtn) {
- SPDLOG_TRACE("task runnable {} finished, rtn: {}", GetFullID(), rtn);
- // set return value
- this->SetRTN(rtn);
+void Task::SafelyRun() { emit SignalRun(); }
- try {
- if (callback_) {
- if (callback_thread_ == QThread::currentThread()) {
- SPDLOG_DEBUG("callback thread is the same thread");
- if (!QMetaObject::invokeMethod(callback_thread_,
- [callback = callback_, rtn = rtn_,
- data_object = data_object_, this]() {
- callback(rtn, data_object);
- // do cleaning work
- emit 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");
- }
- }
- }
- } catch (std::exception &e) {
- SPDLOG_ERROR("exception caught: {}", e.what());
- } catch (...) {
- SPDLOG_ERROR("unknown exception caught");
- }
+int Task::Run() { return p_->Run(); }
- // raise signal, announcing this task come to an end
- SPDLOG_DEBUG("task {}, starting calling signal SignalTaskEnd", GetFullID());
- emit SignalTaskEnd();
+void Task::run() {
+ GF_CORE_LOG_TRACE("interface run() of task {} was called by thread: {}",
+ GetFullID(), QThread::currentThread()->currentThreadId());
+ this->SafelyRun();
}
-void GpgFrontend::Thread::Task::run() {
- SPDLOG_TRACE("task {} starting", GetFullID());
+Task::TaskHandler::TaskHandler(Task *task) : task_(task) {}
- // build runnable package for running
- auto runnable_package = [=, id = GetFullID()]() {
- SPDLOG_DEBUG("task {} runnable start runing", id);
- // Run() will set rtn by itself
- Run();
- // raise signal to anounce after runnable returned
- if (run_callback_after_runnable_finished_) emit 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 Task::TaskHandler::Start() {
+ if (task_ != nullptr) task_->SafelyRun();
}
-void GpgFrontend::Thread::Task::SlotRun() { run(); }
-
-void GpgFrontend::Thread::Task::Run() {
- if (runnable_) {
- SetRTN(runnable_(data_object_));
- } else {
- SPDLOG_WARN("no runnable in task, do callback operation");
- }
+void Task::TaskHandler::Cancel() {
+ if (task_ != nullptr) emit task_->SignalTaskEnd();
}
-GpgFrontend::Thread::Task::DataObject::Destructor *
-GpgFrontend::Thread::Task::DataObject::get_heap_ptr(size_t bytes_size) {
- Destructor *dstr_ptr = new Destructor();
- dstr_ptr->p_obj = malloc(bytes_size);
- return dstr_ptr;
+auto Task::TaskHandler::GetTask() -> Task * {
+ if (task_ != nullptr) return task_;
+ return nullptr;
}
-GpgFrontend::Thread::Task::DataObject::~DataObject() {
- if (!data_objects_.empty())
- SPDLOG_WARN("data_objects_ is not empty",
- "address:", static_cast<void *>(this));
- while (!data_objects_.empty()) {
- free_heap_ptr(data_objects_.top());
- data_objects_.pop();
- }
-}
+void Task::slot_exception_safe_run() noexcept {
+ auto rtn = p_->GetRTN();
+ try {
+ GF_CORE_LOG_TRACE("task runnable {} is starting...", GetFullID());
-size_t GpgFrontend::Thread::Task::DataObject::GetObjectSize() {
- return data_objects_.size();
-}
+ // Run() will set rtn by itself
+ rtn = this->Run();
-void GpgFrontend::Thread::Task::DataObject::free_heap_ptr(Destructor *ptr) {
- SPDLOG_TRACE("p_obj: {} data object: {}",
- static_cast<const void *>(ptr->p_obj),
- static_cast<void *>(this));
- if (ptr->destroy != nullptr) {
- ptr->destroy(ptr->p_obj);
+ GF_CORE_LOG_TRACE("task runnable {} finished, rtn: {}", GetFullID());
+ } catch (...) {
+ GF_CORE_LOG_ERROR("exception was caught at task: {}", GetFullID());
}
- free(const_cast<void *>(ptr->p_obj));
- delete ptr;
-}
-std::string GpgFrontend::Thread::Task::generate_uuid() {
- return boost::uuids::to_string(boost::uuids::random_generator()());
+ // raise signal to anounce after runnable returned
+ if (this->autoDelete()) emit this->SignalTaskShouldEnd(rtn);
}
+auto Task::GetRTN() { return p_->GetRTN(); }
+} // namespace GpgFrontend::Thread \ No newline at end of file
diff --git a/src/core/thread/Task.h b/src/core/thread/Task.h
index ce354697..97a14949 100644
--- a/src/core/thread/Task.h
+++ b/src/core/thread/Task.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -20,23 +20,17 @@
* the gpg4usb project, which is under GPL-3.0-or-later.
*
* All the source code of GpgFrontend was modified and released by
- * Saturneric<[email protected]> starting on May 12, 2021.
+ * Saturneric <[email protected]> starting on May 12, 2021.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
-#ifndef GPGFRONTEND_TASK_H
-#define GPGFRONTEND_TASK_H
-
-#include <functional>
-#include <memory>
-#include <stack>
-#include <string>
-#include <type_traits>
-#include <utility>
+#pragma once
#include "core/GpgFrontendCore.h"
+#include "core/function/SecureMemoryAllocator.h"
+#include "core/model/DataObject.h"
namespace GpgFrontend::Thread {
@@ -45,253 +39,136 @@ class TaskRunner;
class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable {
Q_OBJECT
public:
- class DataObject;
- using DataObjectPtr = std::shared_ptr<DataObject>; ///<
+ friend class TaskRunner;
+
using TaskRunnable = std::function<int(DataObjectPtr)>; ///<
using TaskCallback = std::function<void(int, DataObjectPtr)>; ///<
- static const std::string DEFAULT_TASK_NAME;
-
- friend class TaskRunner;
-
- /**
- * @brief DataObject to be passed to the callback function.
- *
- */
- class GPGFRONTEND_CORE_EXPORT DataObject {
+ class TaskHandler {
public:
- struct Destructor {
- const void *p_obj;
- void (*destroy)(const void *);
- };
-
- /**
- * @brief Get the Objects Size
- *
- * @return size_t
- */
- size_t GetObjectSize();
-
- /**
- * @brief
- *
- * @tparam T
- * @param ptr
- */
- template <typename T>
- void AppendObject(T &&obj) {
- SPDLOG_TRACE("append object: {}", static_cast<void *>(this));
- auto *obj_dstr = this->get_heap_ptr(sizeof(T));
- new ((void *)obj_dstr->p_obj) T(std::forward<T>(obj));
+ explicit TaskHandler(Task*);
- if (std::is_class_v<T>) {
- auto destructor = [](const void *x) {
- static_cast<const T *>(x)->~T();
- };
- obj_dstr->destroy = destructor;
- } else {
- obj_dstr->destroy = nullptr;
- }
+ void Start();
- data_objects_.push(obj_dstr);
- }
+ void Cancel();
- /**
- * @brief
- *
- * @tparam T
- * @param ptr
- */
- template <typename T>
- void AppendObject(T *obj) {
- SPDLOG_TRACE("called: {}", static_cast<void *>(this));
- auto *obj_dstr = this->get_heap_ptr(sizeof(T));
- auto *ptr_heap = new ((void *)obj_dstr->p_obj) T(std::move(*obj));
- if (std::is_class_v<T>) {
- SPDLOG_TRACE("is class");
- auto destructor = [](const void *x) {
- static_cast<const T *>(x)->~T();
- };
- obj_dstr->destroy = destructor;
- } else {
- obj_dstr->destroy = nullptr;
- }
- data_objects_.push(std::move(obj_dstr));
- }
-
- /**
- * @brief
- *
- * @tparam T
- * @return std::shared_ptr<T>
- */
- template <typename T>
- T PopObject() {
- SPDLOG_TRACE("pop object: {}", static_cast<void *>(this));
- if (data_objects_.empty()) throw std::runtime_error("No object to pop");
- auto *obj_dstr = data_objects_.top();
- auto *heap_ptr = (T *)obj_dstr->p_obj;
- auto obj = std::move(*(T *)(heap_ptr));
- this->free_heap_ptr(obj_dstr);
- data_objects_.pop();
- return obj;
- }
-
- /**
- * @brief Destroy the Data Object object
- *
- */
- ~DataObject();
+ auto GetTask() -> Task*;
private:
- std::stack<Destructor *> data_objects_; ///<
-
- /**
- * @brief Get the heap ptr object
- *
- * @param bytes_size
- * @return void*
- */
- Destructor *get_heap_ptr(size_t bytes_size);
-
- /**
- * @brief
- *
- * @param heap_ptr
- */
- void free_heap_ptr(Destructor *);
+ QPointer<Task> task_;
};
/**
* @brief Construct a new Task object
*
*/
- Task(std::string name = DEFAULT_TASK_NAME);
+ explicit Task(QString name);
/**
* @brief Construct a new Task object
*
* @param callback The callback function to be executed.
*/
- explicit Task(TaskRunnable runnable, std::string name = DEFAULT_TASK_NAME,
- DataObjectPtr data_object = nullptr, bool sequency = true);
+ explicit Task(TaskRunnable runnable, QString name,
+ DataObjectPtr data_object = nullptr);
/**
* @brief Construct a new Task object
*
* @param runnable
*/
- explicit Task(
- TaskRunnable runnable, std::string name, DataObjectPtr data,
- TaskCallback callback = [](int, const std::shared_ptr<DataObject> &) {},
- bool sequency = true);
+ explicit Task(TaskRunnable runnable, QString name, DataObjectPtr data,
+ TaskCallback callback);
/**
* @brief Destroy the Task object
*
*/
- virtual ~Task() override;
+ ~Task() override;
/**
- * @brief Run - run the task
+ * @brief
*
+ * @return QString
*/
- virtual void Run();
+ [[nodiscard]] auto GetUUID() const -> QString;
/**
- * @brief
+ * @brief Get the Full I D object
*
- * @return std::string
+ * @return QString
*/
- std::string GetUUID() const;
+ [[nodiscard]] auto GetFullID() const -> QString;
/**
* @brief
*
- * @return std::string
+ * @param hold_on
*/
- std::string GetFullID() const;
+ void HoldOnLifeCycle(bool hold_on);
/**
- * @brief
+ * @brief can be overwrite by subclass
*
- * @return std::string
+ * @return int
*/
- bool GetSequency() const;
-
- public slots:
+ virtual auto Run() -> int;
/**
* @brief
*
+ * @return auto
*/
- void SlotRun();
+ [[nodiscard]] auto GetRTN();
- signals:
- /**
- * @brief announce runnable finished
- *
- */
- void SignalTaskRunnableEnd(int rtn);
+ public slots:
/**
- * @brief runnable and callabck all finished
+ * @brief shouldn't be overwrite by subclass
*
*/
- void SignalTaskEnd();
+ void SafelyRun();
- protected:
- /**
- * @brief Set the Finish After Run object
- *
- * @param finish_after_run
- */
- void SetFinishAfterRun(bool finish_after_run);
+ signals:
/**
* @brief
*
- * @param rtn
*/
- void SetRTN(int rtn);
-
- private:
- const std::string uuid_;
- const std::string name_;
- const bool sequency_ = true; ///< must run in the same thread
- TaskCallback callback_; ///<
- TaskRunnable runnable_; ///<
- bool run_callback_after_runnable_finished_ = true; ///<
- int rtn_ = 0; ///<
- QThread *callback_thread_ = nullptr; ///<
- DataObjectPtr data_object_ = nullptr; ///<
+ void SignalRun();
/**
* @brief
*
*/
- void init();
+ void SignalTaskShouldEnd(int);
/**
* @brief
*
*/
- virtual void run() override;
+ void SignalTaskEnd();
+ protected:
/**
* @brief
*
- * @return std::string
+ * @param rtn
*/
- static std::string generate_uuid();
+ void setRTN(int rtn);
private slots:
+
/**
* @brief
*
*/
- void slot_task_run_callback(int rtn);
+ void slot_exception_safe_run() noexcept;
+
+ private:
+ class Impl;
+ SecureUniquePtr<Impl> p_;
+
+ void run() override;
};
} // namespace GpgFrontend::Thread
-
-#endif // GPGFRONTEND_TASK_H \ No newline at end of file
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
diff --git a/src/core/thread/TaskRunner.h b/src/core/thread/TaskRunner.h
index 35cd1a30..8a93ad0b 100644
--- a/src/core/thread/TaskRunner.h
+++ b/src/core/thread/TaskRunner.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -19,25 +19,22 @@
* 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
*
*/
-#ifndef GPGFRONTEND_TASKRUNNER_H
-#define GPGFRONTEND_TASKRUNNER_H
-
-#include <cstddef>
-#include <mutex>
-#include <queue>
+#pragma once
#include "core/GpgFrontendCore.h"
+#include "core/function/SecureMemoryAllocator.h"
+#include "core/thread/Task.h"
namespace GpgFrontend::Thread {
-class Task;
-
-class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread {
+class GPGFRONTEND_CORE_EXPORT TaskRunner : public QObject {
Q_OBJECT
public:
/**
@@ -50,13 +47,34 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread {
* @brief Destroy the Task Runner object
*
*/
- virtual ~TaskRunner() override;
+ ~TaskRunner() override;
+
+ /**
+ * @brief
+ *
+ */
+ void Start();
/**
* @brief
*
*/
- [[noreturn]] void run() override;
+ void Stop();
+
+ /**
+ * @brief Get the Thread object
+ *
+ * @return QThread*
+ */
+ auto GetThread() -> QThread*;
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ auto IsRunning() -> bool;
public slots:
@@ -70,23 +88,38 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread {
/**
* @brief
*
- * @param task
- * @param seconds
+ * @param runner
+ * @param cb
*/
- void PostScheduleTask(Task* task, size_t seconds);
+ void PostTask(const QString&, const Task::TaskRunnable&,
+ const Task::TaskCallback&, DataObjectPtr);
- 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
+ *
+ * @return std::tuple<QPointer<Task>, TaskTrigger>
+ */
+ auto RegisterTask(const QString&, const Task::TaskRunnable&,
+ const Task::TaskCallback&, DataObjectPtr)
+ -> Task::TaskHandler;
+
+ /**
+ * @brief
+ *
+ * @param task
+ */
+ void PostConcurrentTask(Task* task);
/**
* @brief
*
+ * @param task
+ * @param seconds
*/
- void unregister_finished_task(std::string);
+ void PostScheduleTask(Task* task, size_t seconds);
+
+ private:
+ class Impl;
+ SecureUniquePtr<Impl> p_;
};
} // namespace GpgFrontend::Thread
-
-#endif // GPGFRONTEND_TASKRUNNER_H \ No newline at end of file
diff --git a/src/core/thread/TaskRunnerGetter.cpp b/src/core/thread/TaskRunnerGetter.cpp
index 186483ec..bdcd89d0 100644
--- a/src/core/thread/TaskRunnerGetter.cpp
+++ b/src/core/thread/TaskRunnerGetter.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -19,28 +19,46 @@
* 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/TaskRunnerGetter.h"
-GpgFrontend::Thread::TaskRunnerGetter::TaskRunnerGetter(int channel)
- : SingletonFunctionObject<TaskRunnerGetter>(channel) {}
+#include <mutex>
+
+#include "core/GpgConstants.h"
+#include "core/thread/TaskRunner.h"
+
+namespace GpgFrontend::Thread {
-GpgFrontend::Thread::TaskRunner*
-GpgFrontend::Thread::TaskRunnerGetter::GetTaskRunner(
- TaskRunnerType runner_type) {
+TaskRunnerGetter::TaskRunnerGetter(int)
+ : SingletonFunctionObject<TaskRunnerGetter>(kGpgFrontendDefaultChannel) {}
+
+auto TaskRunnerGetter::GetTaskRunner(TaskRunnerType runner_type)
+ -> TaskRunnerPtr {
+ std::lock_guard<std::mutex> lock_guard(task_runners_map_lock_);
while (true) {
auto it = task_runners_.find(runner_type);
if (it != task_runners_.end()) {
return it->second;
- } else {
- auto runner = new TaskRunner();
- task_runners_[runner_type] = runner;
- runner->start();
- continue;
+ }
+
+ auto runner = GpgFrontend::SecureCreateSharedObject<TaskRunner>();
+ task_runners_[runner_type] = runner;
+ runner->Start();
+ }
+}
+
+void TaskRunnerGetter::StopAllTeakRunner() {
+ for (const auto& [key, value] : task_runners_) {
+ if (value->IsRunning()) {
+ value->Stop();
}
}
}
+
+} // namespace GpgFrontend::Thread \ No newline at end of file
diff --git a/src/core/thread/TaskRunnerGetter.h b/src/core/thread/TaskRunnerGetter.h
index 80b25c3e..49ed25c0 100644
--- a/src/core/thread/TaskRunnerGetter.h
+++ b/src/core/thread/TaskRunnerGetter.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -19,20 +19,25 @@
* 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
*
*/
-#ifndef GPGFRONTEND_TASKRUNNERGETTER_H
-#define GPGFRONTEND_TASKRUNNERGETTER_H
+#pragma once
+
+#include <mutex>
#include "core/GpgFrontendCore.h"
-#include "core/GpgFunctionObject.h"
+#include "core/function/basic/GpgFunctionObject.h"
#include "core/thread/TaskRunner.h"
namespace GpgFrontend::Thread {
+using TaskRunnerPtr = std::shared_ptr<TaskRunner>;
+
class GPGFRONTEND_CORE_EXPORT TaskRunnerGetter
: public GpgFrontend::SingletonFunctionObject<TaskRunnerGetter> {
public:
@@ -41,18 +46,21 @@ class GPGFRONTEND_CORE_EXPORT TaskRunnerGetter
kTaskRunnerType_GPG,
kTaskRunnerType_IO,
kTaskRunnerType_Network,
+ kTaskRunnerType_Module,
kTaskRunnerType_External_Process,
};
- TaskRunnerGetter(int channel = SingletonFunctionObject::GetDefaultChannel());
+ explicit TaskRunnerGetter(
+ int channel = SingletonFunctionObject::GetDefaultChannel());
- TaskRunner *GetTaskRunner(
- TaskRunnerType runner_type = kTaskRunnerType_Default);
+ auto GetTaskRunner(TaskRunnerType runner_type = kTaskRunnerType_Default)
+ -> TaskRunnerPtr;
+
+ void StopAllTeakRunner();
private:
- std::map<TaskRunnerType, TaskRunner *> task_runners_;
+ std::map<TaskRunnerType, TaskRunnerPtr> task_runners_;
+ std::mutex task_runners_map_lock_;
};
} // namespace GpgFrontend::Thread
-
-#endif // GPGFRONTEND_TASKRUNNERGETTER_H \ No newline at end of file
diff --git a/src/core/thread/ThreadingModel.h b/src/core/thread/ThreadingModel.h
index eb6c9039..2fcc11c8 100644
--- a/src/core/thread/ThreadingModel.h
+++ b/src/core/thread/ThreadingModel.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -20,17 +20,14 @@
* the gpg4usb project, which is under GPL-3.0-or-later.
*
* All the source code of GpgFrontend was modified and released by
- * Saturneric<[email protected]> starting on May 12, 2021.
+ * Saturneric <[email protected]> starting on May 12, 2021.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
-#ifndef GPGFRONTEND_THREADINGMODEL_H
-#define GPGFRONTEND_THREADINGMODEL_H
+#pragma once
#include "core/thread/Task.h"
#include "core/thread/TaskRunner.h"
#include "core/thread/TaskRunnerGetter.h"
-
-#endif // GPGFRONTEND_THREADINGMODEL_H \ No newline at end of file