From c9a99ac0300a4e44197129c65419a6a18d2bea4c Mon Sep 17 00:00:00 2001 From: Nova Date: Sat, 30 Aug 2025 01:47:23 +0330 Subject: [PATCH] Revert "improve thread management" This reverts commit 3f3b268916679ab2d58acce9ae2194c55ea3ede2. --- 3rdparty/QThreadCreateThread.hpp | 39 +++++++++++++ 3rdparty/qscopeguard.h | 96 ++++++++++++++++++++++++++++++++ include/global/Utils.hpp | 2 +- src/global/Utils.cpp | 30 ++++++++-- 4 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 3rdparty/QThreadCreateThread.hpp create mode 100644 3rdparty/qscopeguard.h diff --git a/3rdparty/QThreadCreateThread.hpp b/3rdparty/QThreadCreateThread.hpp new file mode 100644 index 0000000..ba6fe5f --- /dev/null +++ b/3rdparty/QThreadCreateThread.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +// FOR OLD QT + +class QThreadCreateThread : public QThread { +public: + explicit QThreadCreateThread(std::future &&future) + : m_future(std::move(future)) { + // deleteLater + connect(this, &QThread::finished, this, &QThread::deleteLater); + } + +private: + void run() override { + m_future.get(); + } + + std::future m_future; +}; + +inline QThread *createThreadImpl(std::future &&future) { + return new QThreadCreateThread(std::move(future)); +} + +template +QThread *createQThread(Function &&f, Args &&... args) { + using DecayedFunction = typename std::decay::type; + auto threadFunction = + [f = static_cast(std::forward(f))](auto &&... largs) mutable -> void { + (void) std::invoke(std::move(f), std::forward(largs)...); + }; + + return createThreadImpl(std::async(std::launch::deferred, + std::move(threadFunction), + std::forward(args)...)); +} diff --git a/3rdparty/qscopeguard.h b/3rdparty/qscopeguard.h new file mode 100644 index 0000000..31100fc --- /dev/null +++ b/3rdparty/qscopeguard.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCOPEGUARD_H +#define QSCOPEGUARD_H + +#include + + +QT_BEGIN_NAMESPACE + + +template class QScopeGuard; +template QScopeGuard qScopeGuard(F f); + +template +class QScopeGuard +{ +public: + QScopeGuard(QScopeGuard &&other) Q_DECL_NOEXCEPT + : m_func(std::move(other.m_func)) + , m_invoke(other.m_invoke) + { + other.dismiss(); + } + + ~QScopeGuard() + { + if (m_invoke) + m_func(); + } + + void dismiss() Q_DECL_NOEXCEPT + { + m_invoke = false; + } + +private: + explicit QScopeGuard(F f) Q_DECL_NOEXCEPT + : m_func(std::move(f)) + { + } + + Q_DISABLE_COPY(QScopeGuard) + + F m_func; + bool m_invoke = true; + friend QScopeGuard qScopeGuard(F); +}; + + +template +QScopeGuard qScopeGuard(F f) +{ + return QScopeGuard(std::move(f)); +} + +QT_END_NAMESPACE + +#endif // QSCOPEGUARD_H diff --git a/include/global/Utils.hpp b/include/global/Utils.hpp index 7daf328..28fc945 100644 --- a/include/global/Utils.hpp +++ b/include/global/Utils.hpp @@ -22,7 +22,7 @@ inline QWidget *mainwindow; inline std::function MW_show_log; inline std::function MW_dialog_message; -// Threading +// Dispatchers class QThread; inline QThread *DS_cores; diff --git a/src/global/Utils.cpp b/src/global/Utils.cpp index bf67326..45504d2 100644 --- a/src/global/Utils.cpp +++ b/src/global/Utils.cpp @@ -1,6 +1,7 @@ #include "include/global/Utils.hpp" #include "3rdparty/base64.h" +#include "3rdparty/QThreadCreateThread.hpp" #include @@ -16,7 +17,6 @@ #include #include #include -#include #ifdef Q_OS_WIN #include "include/sys/windows/guihelper.h" @@ -250,15 +250,37 @@ void ActivateWindow(QWidget *w) { } void runOnUiThread(const std::function &callback) { - QMetaObject::invokeMethod(mainwindow, callback); + // any thread + auto *timer = new QTimer(); + auto thread = mainwindow->thread(); + timer->moveToThread(thread); + timer->setSingleShot(true); + QObject::connect(timer, &QTimer::timeout, [=]() { + // main thread + callback(); + timer->deleteLater(); + }); + QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0)); } void runOnNewThread(const std::function &callback) { - QThreadPool::globalInstance()->start(callback); + createQThread(callback)->start(); } void runOnThread(const std::function &callback, QObject *parent) { - QMetaObject::invokeMethod(parent, callback); + auto *timer = new QTimer(); + auto thread = dynamic_cast(parent); + if (thread == nullptr) { + timer->moveToThread(parent->thread()); + } else { + timer->moveToThread(thread); + } + timer->setSingleShot(true); + QObject::connect(timer, &QTimer::timeout, [=]() { + callback(); + timer->deleteLater(); + }); + QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0)); } void setTimeout(const std::function &callback, QObject *obj, int timeout) {