Commit 72af6b78 authored by Eike Ziller's avatar Eike Ziller

runAsync: Remove ResultType template parameter.

It is now deduced from either the type of the
QFutureInterface<ResultType> function argument, or the return type.

Change-Id: Iddab3cc329206c649a6e55a44b2de2d406701dee
Reviewed-by: default avatarTobias Hunger <tobias.hunger@theqtcompany.com>
parent ece316fb
......@@ -319,10 +319,10 @@ QFuture<void> ModelManagerInterface::refreshSourceFiles(const QStringList &sourc
if (sourceFiles.isEmpty())
return QFuture<void>();
QFuture<void> result = Utils::runAsync<void>(&ModelManagerInterface::parse,
workingCopyInternal(), sourceFiles,
this, Dialect(Dialect::Qml),
emitDocumentOnDiskChanged);
QFuture<void> result = Utils::runAsync(&ModelManagerInterface::parse,
workingCopyInternal(), sourceFiles,
this, Dialect(Dialect::Qml),
emitDocumentOnDiskChanged);
cleanupFutures();
m_futures.append(result);
......@@ -348,9 +348,9 @@ QFuture<void> ModelManagerInterface::refreshSourceFiles(const QStringList &sourc
void ModelManagerInterface::fileChangedOnDisk(const QString &path)
{
Utils::runAsync<void>(&ModelManagerInterface::parse,
workingCopyInternal(), QStringList() << path,
this, Dialect(Dialect::AnyLanguage), true);
Utils::runAsync(&ModelManagerInterface::parse,
workingCopyInternal(), QStringList() << path,
this, Dialect(Dialect::AnyLanguage), true);
}
void ModelManagerInterface::removeFiles(const QStringList &files)
......@@ -1096,9 +1096,9 @@ void ModelManagerInterface::maybeScan(const PathsAndLanguages &importPaths)
}
if (pathToScan.length() > 1) {
QFuture<void> result = Utils::runAsync<void>(&ModelManagerInterface::importScan,
workingCopyInternal(), pathToScan,
this, true, true);
QFuture<void> result = Utils::runAsync(&ModelManagerInterface::importScan,
workingCopyInternal(), pathToScan,
this, true, true);
cleanupFutures();
m_futures.append(result);
......@@ -1243,7 +1243,7 @@ void ModelManagerInterface::startCppQmlTypeUpdate()
if (!cppModelManager)
return;
m_cppQmlTypesUpdater = Utils::runAsync<void>(&ModelManagerInterface::updateCppQmlTypes,
m_cppQmlTypesUpdater = Utils::runAsync(&ModelManagerInterface::updateCppQmlTypes,
this, cppModelManager->snapshot(), m_queuedCppDocuments);
m_queuedCppDocuments.clear();
}
......
......@@ -435,6 +435,138 @@ QT_END_NAMESPACE
namespace Utils {
namespace Internal {
/*
resultType<F>::type
Returns the type of results that would be reported by a callable of type F
when called through the runAsync methods. I.e. the ResultType in
void f(QFutureInterface<Result> &fi, ...)
ResultType f(...)
Returns void if F is not callable, and if F is a callable that does not take
a QFutureInterface& as its first parameter and returns void.
*/
template<typename T>
struct hasCallOperator
{
using yes = char;
using no = struct { char foo[2]; };
template<typename C>
static yes test(decltype(&C::operator()));
template<typename C>
static no test(...);
static const bool value = (sizeof(test<T>(0)) == sizeof(yes));
};
template <typename Function>
struct resultType;
template <typename Function, typename Arg>
struct resultTypeWithArgument;
template <typename Function, int index, bool>
struct resultTypeTakesArguments;
template <typename Function, bool>
struct resultTypeIsMemberFunction;
template <typename Function, bool>
struct resultTypeIsFunctionLike;
template <typename Function, bool>
struct resultTypeHasCallOperator;
template <typename Function, typename ResultType>
struct resultTypeWithArgument<Function, QFutureInterface<ResultType>&>
{
using type = ResultType;
};
template <typename Function, typename Arg>
struct resultTypeWithArgument
{
using type = typename functionTraits<Function>::ResultType;
};
template <typename Function, int index>
struct resultTypeTakesArguments<Function, index, true>
: public resultTypeWithArgument<Function, typename functionTraits<Function>::template argument<index>::type>
{
};
template <typename Function, int index>
struct resultTypeTakesArguments<Function, index, false>
{
using type = typename functionTraits<Function>::ResultType;
};
template <typename Function>
struct resultTypeIsFunctionLike<Function, true>
: public resultTypeTakesArguments<Function, 0, (functionTraits<Function>::arity > 0)>
{
};
template <typename Function>
struct resultTypeIsMemberFunction<Function, true>
: public resultTypeTakesArguments<Function, 1, (functionTraits<Function>::arity > 1)>
{
};
template <typename Function>
struct resultTypeIsMemberFunction<Function, false>
{
using type = void;
};
template <typename Function>
struct resultTypeIsFunctionLike<Function, false>
: public resultTypeIsMemberFunction<Function, std::is_member_function_pointer<Function>::value>
{
};
template <typename Function>
struct resultTypeHasCallOperator<Function, false>
: public resultTypeIsFunctionLike<Function, std::is_function<typename std::remove_pointer<typename std::decay<Function>::type>::type>::value>
{
};
template <typename Callable>
struct resultTypeHasCallOperator<Callable, true>
: public resultTypeTakesArguments<decltype(&Callable::operator()), 1, (functionTraits<decltype(&Callable::operator())>::arity > 1)>
{
};
template <typename Function>
struct resultType
: public resultTypeHasCallOperator<Function, hasCallOperator<Function>::value>
{
};
template <typename Function>
struct resultType<Function&> : public resultType<Function>
{
};
template <typename Function>
struct resultType<const Function&> : public resultType<Function>
{
};
template <typename Function>
struct resultType<Function &&> : public resultType<Function>
{
};
/*
Callable object that wraps a member function pointer with the object it
will be called on.
*/
template <typename Function>
class MemberCallable;
......@@ -478,6 +610,10 @@ private:
Obj *m_obj;
};
/*
Helper functions for runAsync that run in the started thread.
*/
// void function that does not take QFutureInterface
template <typename ResultType, typename Function, typename... Args>
void runAsyncReturnVoidDispatch(std::true_type, QFutureInterface<ResultType> futureInterface, Function &&function, Args&&... args)
......@@ -557,6 +693,11 @@ void runAsyncImpl(QFutureInterface<ResultType> futureInterface, Function &&funct
std::forward<Args>(args)...);
}
/*
AsyncJob is a QRunnable that wraps a function with the
arguments that are passed to it when it is run in a thread.
*/
// can be replaced with std::(make_)index_sequence with C++14
template <std::size_t...>
struct indexSequence { };
......@@ -671,9 +812,10 @@ private:
\sa QThreadPool
\sa QThread::Priority
*/
template <typename ResultType, typename Function, typename... Args>
QFuture<ResultType> runAsync(QThreadPool *pool, QThread::Priority priority,
Function &&function, Args&&... args)
template <typename Function, typename... Args,
typename ResultType = typename Internal::resultType<Function>::type>
QFuture<ResultType>
runAsync(QThreadPool *pool, QThread::Priority priority, Function &&function, Args&&... args)
{
auto job = new Internal::AsyncJob<ResultType,Function,Args...>
(std::forward<Function>(function), std::forward<Args>(args)...);
......@@ -696,11 +838,13 @@ QFuture<ResultType> runAsync(QThreadPool *pool, QThread::Priority priority,
\sa runAsync(QThreadPool*,QThread::Priority,Function&&,Args&&...)
\sa QThread::Priority
*/
template <typename ResultType, typename Function, typename... Args>
QFuture<ResultType> runAsync(QThread::Priority priority, Function &&function, Args&&... args)
template <typename Function, typename... Args,
typename ResultType = typename Internal::resultType<Function>::type>
QFuture<ResultType>
runAsync(QThread::Priority priority, Function &&function, Args&&... args)
{
return runAsync<ResultType>(static_cast<QThreadPool *>(nullptr), priority,
std::forward<Function>(function), std::forward<Args>(args)...);
return runAsync(static_cast<QThreadPool *>(nullptr), priority,
std::forward<Function>(function), std::forward<Args>(args)...);
}
/*!
......@@ -708,16 +852,18 @@ QFuture<ResultType> runAsync(QThread::Priority priority, Function &&function, Ar
\sa runAsync(QThreadPool*,QThread::Priority,Function&&,Args&&...)
\sa QThread::Priority
*/
template <typename ResultType, typename Function, typename... Args,
template <typename Function, typename... Args,
typename = typename std::enable_if<
!std::is_same<typename std::decay<Function>::type, QThreadPool>::value
&& !std::is_same<typename std::decay<Function>::type, QThread::Priority>::value
>::type>
QFuture<ResultType> runAsync(Function &&function, Args&&... args)
{
return runAsync<ResultType>(static_cast<QThreadPool *>(nullptr),
QThread::InheritPriority, std::forward<Function>(function),
std::forward<Args>(args)...);
>::type,
typename ResultType = typename Internal::resultType<Function>::type>
QFuture<ResultType>
runAsync(Function &&function, Args&&... args)
{
return runAsync(static_cast<QThreadPool *>(nullptr),
QThread::InheritPriority, std::forward<Function>(function),
std::forward<Args>(args)...);
}
/*!
......@@ -725,15 +871,16 @@ QFuture<ResultType> runAsync(Function &&function, Args&&... args)
\sa runAsync(QThreadPool*,QThread::Priority,Function&&,Args&&...)
\sa QThread::Priority
*/
template <typename ResultType, typename Function, typename... Args,
template <typename Function, typename... Args,
typename = typename std::enable_if<
!std::is_same<typename std::decay<Function>::type, QThread::Priority>::value
>::type>
QFuture<ResultType> runAsync(QThreadPool *pool,
Function &&function, Args&&... args)
>::type,
typename ResultType = typename Internal::resultType<Function>::type>
QFuture<ResultType>
runAsync(QThreadPool *pool, Function &&function, Args&&... args)
{
return runAsync<ResultType>(pool, QThread::InheritPriority, std::forward<Function>(function),
std::forward<Args>(args)...);
return runAsync(pool, QThread::InheritPriority, std::forward<Function>(function),
std::forward<Args>(args)...);
}
} // Utils
......
......@@ -222,7 +222,7 @@ void ShellCommand::execute()
if (d->m_jobs.empty())
return;
QFuture<void> task = Utils::runAsync<void>(&ShellCommand::run, this);
QFuture<void> task = Utils::runAsync(&ShellCommand::run, this);
d->m_watcher.setFuture(task);
addTask(task);
}
......
......@@ -738,7 +738,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
}
QFuture<TestParseResult> future
= Utils::runAsync<TestParseResult>(&performParse, list, referencingFiles);
= Utils::runAsync(&performParse, list, referencingFiles);
m_futureWatcher.setFuture(future);
if (list.size() > 5) {
Core::ProgressManager::addTask(future, tr("Scanning for Tests"),
......
......@@ -285,8 +285,8 @@ void TestRunner::runTests()
const QSharedPointer<TestSettings> settings = AutotestPlugin::instance()->settings();
const QString &metricsOption = TestSettings::metricsTypeToOption(settings->metrics);
QFuture<TestResult *> future = Utils::runAsync<TestResult *>(&performTestRun, m_selectedTests,
settings->timeout, metricsOption);
QFuture<TestResult *> future = Utils::runAsync(&performTestRun, m_selectedTests,
settings->timeout, metricsOption);
m_futureWatcher.setFuture(future);
Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX);
}
......
......@@ -45,9 +45,8 @@ QList<LocatorFilterEntry> BasicLocatorFilterTest::matchesFor(const QString &sear
doBeforeLocatorRun();
const QList<ILocatorFilter *> filters = QList<ILocatorFilter *>() << m_filter;
m_filter->prepareSearch(searchText);
QFuture<LocatorFilterEntry> locatorSearch = Utils::runAsync<LocatorFilterEntry>(&Internal::runSearch,
filters,
searchText);
QFuture<LocatorFilterEntry> locatorSearch = Utils::runAsync(&Internal::runSearch, filters,
searchText);
locatorSearch.waitForFinished();
doAfterLocatorRun();
return locatorSearch.results();
......
......@@ -520,8 +520,7 @@ void LocatorWidget::updateCompletionList(const QString &text)
foreach (ILocatorFilter *filter, filters)
filter->prepareSearch(searchText);
QFuture<LocatorFilterEntry> future = Utils::runAsync<LocatorFilterEntry>(&runSearch, filters,
searchText);
QFuture<LocatorFilterEntry> future = Utils::runAsync(&runSearch, filters, searchText);
m_entriesWatcher->setFuture(future);
}
......
......@@ -235,7 +235,7 @@ void GitGrep::writeSettings(QSettings *settings) const
QFuture<FileSearchResultList> GitGrep::executeSearch(
const TextEditor::FileFindParameters &parameters)
{
return Utils::runAsync<FileSearchResultList>(GitGrepRunner::run, parameters);
return Utils::runAsync(GitGrepRunner::run, parameters);
}
} // Internal
......
......@@ -1806,10 +1806,10 @@ void QmakeProFileNode::asyncUpdate()
m_readerExact->setExact(false);
m_parseFutureWatcher.waitForFinished();
EvalInput input = evalInput();
QFuture<EvalResult *> future = Utils::runAsync<EvalResult *>(ProjectExplorerPlugin::sharedThreadPool(),
QThread::LowestPriority,
&QmakeProFileNode::asyncEvaluate,
this, input);
QFuture<EvalResult *> future = Utils::runAsync(ProjectExplorerPlugin::sharedThreadPool(),
QThread::LowestPriority,
&QmakeProFileNode::asyncEvaluate,
this, input);
m_parseFutureWatcher.setFuture(future);
}
......
......@@ -891,10 +891,8 @@ void FindReferences::findUsages(const QString &fileName, quint32 offset)
{
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
QFuture<Usage> result = Utils::runAsync<Usage>(
&find_helper, modelManager->workingCopy(),
modelManager->snapshot(), fileName, offset,
QString());
QFuture<Usage> result = Utils::runAsync(&find_helper, modelManager->workingCopy(),
modelManager->snapshot(), fileName, offset, QString());
m_watcher.setFuture(result);
}
......@@ -908,10 +906,8 @@ void FindReferences::renameUsages(const QString &fileName, quint32 offset,
if (newName.isNull())
newName = QLatin1String("");
QFuture<Usage> result = Utils::runAsync<Usage>(
&find_helper, modelManager->workingCopy(),
modelManager->snapshot(), fileName, offset,
newName);
QFuture<Usage> result = Utils::runAsync(&find_helper, modelManager->workingCopy(),
modelManager->snapshot(), fileName, offset, newName);
m_watcher.setFuture(result);
}
......
......@@ -545,8 +545,8 @@ void SemanticHighlighter::rerun(const QmlJSTools::SemanticInfo &semanticInfo)
m_watcher.cancel();
m_startRevision = m_document->document()->revision();
m_watcher.setFuture(Utils::runAsync<Use>(QThread::LowestPriority,
&SemanticHighlighter::run, this, semanticInfo));
m_watcher.setFuture(Utils::runAsync(QThread::LowestPriority,
&SemanticHighlighter::run, this, semanticInfo));
}
void SemanticHighlighter::cancel()
......
......@@ -152,7 +152,7 @@ void QmlTaskManager::updateMessagesNow(bool updateSemantic)
// process them
QFuture<FileErrorMessages> future =
Utils::runAsync<FileErrorMessages>(
Utils::runAsync(
&collectMessages, modelManager->newestSnapshot(), modelManager->projectInfos(),
modelManager->defaultVContext(Dialect::AnyLanguage), updateSemantic);
m_messageCollector.setFuture(future);
......
......@@ -347,7 +347,7 @@ void QmlProfilerModelManager::save(const QString &filename)
connect(writer, &QObject::destroyed, this, &QmlProfilerModelManager::saveFinished,
Qt::QueuedConnection);
QFuture<void> result = Utils::runAsync<void>([file, writer] (QFutureInterface<void> &future) {
QFuture<void> result = Utils::runAsync([file, writer] (QFutureInterface<void> &future) {
writer->setFuture(&future);
writer->save(file);
delete writer;
......@@ -387,7 +387,7 @@ void QmlProfilerModelManager::load(const QString &filename)
acquiringDone();
}, Qt::QueuedConnection);
QFuture<void> result = Utils::runAsync<void>([file, reader] (QFutureInterface<void> &future) {
QFuture<void> result = Utils::runAsync([file, reader] (QFutureInterface<void> &future) {
reader->setFuture(&future);
reader->load(file);
file->close();
......
......@@ -322,7 +322,7 @@ void Manager::registerHighlightingFiles()
if (!m_registeringWatcher.isRunning()) {
clear();
QFuture<RegisterData> future = Utils::runAsync<RegisterData>(ManagerProcessor());
QFuture<RegisterData> future = Utils::runAsync(ManagerProcessor());
m_registeringWatcher.setFuture(future);
} else {
m_hasQueuedRegistration = true;
......
......@@ -250,8 +250,8 @@ bool CleanDialog::promptToDelete()
return false;
// Remove in background
QFuture<void> task = Utils::runAsync<void>(Internal::runCleanFiles, d->m_workingDirectory,
selectedFiles, Internal::handleError);
QFuture<void> task = Utils::runAsync(Internal::runCleanFiles, d->m_workingDirectory,
selectedFiles, Internal::handleError);
const QString taskName = tr("Cleaning \"%1\"").
arg(QDir::toNativeSeparators(d->m_workingDirectory));
......
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