Commit 4a954c29 authored by Eike Ziller's avatar Eike Ziller

runAsync: Fix unexpected behavior for using singleShot/timers etc

Timers/singleShot etc can only be used in QThreads (they require the
event dispatcher). So we have to use QThreads instead of std::threads to
nicely interoperate with Qt features.

Task-number: QTCREATORBUG-15681
Change-Id: I851e2f102e15ccd3347d455cc9d8b7df935c2d5e
Reviewed-by: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent 2cf00605
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** 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 General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** 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-3.0.html.
**
****************************************************************************/
#include "runextensions.h"
namespace Utils {
namespace Internal {
RunnableThread::RunnableThread(QRunnable *runnable, QObject *parent)
: QThread(parent),
m_runnable(runnable)
{
}
void RunnableThread::run()
{
m_runnable->run();
if (m_runnable->autoDelete())
delete m_runnable;
deleteLater();
}
} // Internal
} // Utils
......@@ -27,11 +27,13 @@
#define RUNEXTENSIONS_H
#include "qtcassert.h"
#include "utils_global.h"
#include <QCoreApplication>
#include <QFuture>
#include <QFutureInterface>
#include <QRunnable>
#include <QThread>
#include <QThreadPool>
#include <chrono>
......@@ -618,6 +620,18 @@ private:
QThread::Priority priority = QThread::InheritPriority;
};
class QTCREATOR_UTILS_EXPORT RunnableThread : public QThread
{
public:
explicit RunnableThread(QRunnable *runnable, QObject *parent = 0);
protected:
void run();
private:
QRunnable *m_runnable;
};
} // Internal
template <typename ReduceResult, typename Container, typename InitFunction, typename MapFunction,
......@@ -665,11 +679,11 @@ template <typename ResultType, typename Function, typename... Args,
>::type>
QFuture<ResultType> runAsync(Function &&function, Args&&... args)
{
QFutureInterface<ResultType> futureInterface;
futureInterface.reportStarted();
std::thread(Internal::runAsyncImpl<ResultType,typename std::decay<Function>::type,typename std::decay<Args>::type...>,
futureInterface, std::forward<Function>(function), std::forward<Args>(args)...).detach();
return futureInterface.future();
auto job = new Internal::AsyncJob<ResultType,Function,Args...>
(std::forward<Function>(function), std::forward<Args>(args)...);
QFuture<ResultType> future = job->future();
(new Internal::RunnableThread(job))->start(); // automatically deletes itself
return future;
}
template <typename ResultType, typename Function, typename... Args>
......
......@@ -99,7 +99,8 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/categorysortfiltermodel.cpp \
$$PWD/dropsupport.cpp \
$$PWD/icon.cpp \
$$PWD/port.cpp
$$PWD/port.cpp \
$$PWD/runextensions.cpp
win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp
......
......@@ -166,6 +166,7 @@ QtcLibrary {
"qtcprocess.h",
"reloadpromptutils.cpp",
"reloadpromptutils.h",
"runextensions.cpp",
"runextensions.h",
"savedaction.cpp",
"savedaction.h",
......
QTC_LIB_DEPENDS = utils
include(../qttest.pri)
# Input
......
......@@ -2,7 +2,7 @@ import qbs
QtcAutotest {
name: "Run extensions autotest"
cpp.includePaths: base.concat(project.ide_source_tree + "/src/libs")
Depends { name: "Utils" }
files: [
"tst_runextensions.cpp",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment