diff --git a/src/libs/utils/runextensions.h b/src/libs/utils/runextensions.h index 49752234630..14cf5e49223 100644 --- a/src/libs/utils/runextensions.h +++ b/src/libs/utils/runextensions.h @@ -26,6 +26,7 @@ #pragma once #include "functiontraits.h" +#include "optional.h" #include "utils_global.h" #include @@ -57,6 +58,9 @@ struct hasCallOperator }; namespace Utils { + +using StackSizeInBytes = Utils::optional; + namespace Internal { /* @@ -388,6 +392,34 @@ private: QRunnable *m_runnable; }; +template::type> +QFuture runAsync_internal(QThreadPool *pool, + StackSizeInBytes stackSize, + QThread::Priority priority, + Function &&function, + Args &&... args) +{ + Q_ASSERT(!(pool && stackSize)); // stack size cannot be changed once a thread is started + auto job = new Internal::AsyncJob + (std::forward(function), std::forward(args)...); + job->setThreadPriority(priority); + QFuture future = job->future(); + if (pool) { + job->setThreadPool(pool); + pool->start(job); + } else { + auto thread = new Internal::RunnableThread(job); + if (stackSize) + thread->setStackSize(stackSize.value()); + thread->moveToThread(qApp->thread()); // make sure thread gets deleteLater on main thread + QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater); + thread->start(priority); + } + return future; +} + } // Internal /*! @@ -418,20 +450,11 @@ template runAsync(QThreadPool *pool, QThread::Priority priority, Function &&function, Args&&... args) { - auto job = new Internal::AsyncJob - (std::forward(function), std::forward(args)...); - job->setThreadPriority(priority); - QFuture future = job->future(); - if (pool) { - job->setThreadPool(pool); - pool->start(job); - } else { - auto thread = new Internal::RunnableThread(job); - thread->moveToThread(qApp->thread()); // make sure thread gets deleteLater on main thread - QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater); - thread->start(priority); - } - return future; + return Internal::runAsync_internal(pool, + StackSizeInBytes(), + priority, + std::forward(function), + std::forward(args)...); } /*! @@ -448,6 +471,47 @@ runAsync(QThread::Priority priority, Function &&function, Args&&... args) std::forward(function), std::forward(args)...); } +/*! + Runs \a function with \a args in a new thread with given thread \a stackSize and + thread priority QThread::InheritPriority . + \sa runAsync(QThreadPool*,QThread::Priority,Function&&,Args&&...) + \sa QThread::Priority + \sa QThread::setStackSize +*/ +template::type> +QFuture runAsync(Utils::StackSizeInBytes stackSize, Function &&function, Args &&... args) +{ + return Internal::runAsync_internal(static_cast(nullptr), + stackSize, + QThread::InheritPriority, + std::forward(function), + std::forward(args)...); +} + +/*! + Runs \a function with \a args in a new thread with given thread \a stackSize and + given thread \a priority. + \sa runAsync(QThreadPool*,QThread::Priority,Function&&,Args&&...) + \sa QThread::Priority + \sa QThread::setStackSize +*/ +template::type> +QFuture runAsync(Utils::StackSizeInBytes stackSize, + QThread::Priority priority, + Function &&function, + Args &&... args) +{ + return Internal::runAsync_internal(static_cast(nullptr), + stackSize, + priority, + std::forward(function), + std::forward(args)...); +} + /*! Runs \a function with \a args in a new thread with thread priority QThread::InheritPriority. \sa runAsync(QThreadPool*,QThread::Priority,Function&&,Args&&...) diff --git a/tests/auto/runextensions/tst_runextensions.cpp b/tests/auto/runextensions/tst_runextensions.cpp index acad21b15d2..fd0c6609d8b 100644 --- a/tests/auto/runextensions/tst_runextensions.cpp +++ b/tests/auto/runextensions/tst_runextensions.cpp @@ -42,6 +42,8 @@ private slots: void moveOnlyType(); #endif void threadPriority(); + void threadSize(); + void threadSizeAndPriority(); void runAsyncNoFutureInterface(); void crefFunction(); void onResultReady(); @@ -399,6 +401,19 @@ void tst_RunExtensions::threadPriority() QList({0, 2, 1})); } +void tst_RunExtensions::threadSize() +{ + QCOMPARE(Utils::runAsync(Utils::StackSizeInBytes(1024 * 1024), report3).results(), + QList({0, 2, 1})); +} + +void tst_RunExtensions::threadSizeAndPriority() +{ + QCOMPARE(Utils::runAsync(Utils::StackSizeInBytes(1024 * 1024), QThread::LowestPriority, report3) + .results(), + QList({0, 2, 1})); +} + void tst_RunExtensions::runAsyncNoFutureInterface() { // free function pointer