forked from qt-creator/qt-creator
Tasking: Introduce ConcurrentCall
It substitutes Utils::Async, but is Utils independent. The ConcurrentCall class is prepared to work with TaskTree. Provide the task tree adapter for the ConcurrentCall class. Register the task inside the Tasking namespace under the ConcurrentCallTask name. This class introduces the dependency to Qt::Concurrent, otherwise Tasking namespace is independent on Qt::Concurrent. Possibly, may be added into Qt::Concurrent lib, as a wrapper around the QtConcurrent::run() call. Change-Id: I4511ff0430e78346aa6a4fae1a9d5370fdd08506 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
add_qtc_library(Tasking OBJECT
|
add_qtc_library(Tasking OBJECT
|
||||||
# Never add dependencies to non-Qt libraries for this library
|
# Never add dependencies to non-Qt libraries for this library
|
||||||
DEPENDS Qt::Core
|
DEPENDS Qt::Concurrent Qt::Core
|
||||||
PUBLIC_DEFINES TASKING_LIBRARY
|
PUBLIC_DEFINES TASKING_LIBRARY
|
||||||
SOURCES
|
SOURCES
|
||||||
barrier.cpp barrier.h
|
barrier.cpp barrier.h
|
||||||
|
concurrentcall.h
|
||||||
tasking_global.h
|
tasking_global.h
|
||||||
tasktree.cpp tasktree.h
|
tasktree.cpp tasktree.h
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ private:
|
|||||||
int m_current = -1;
|
int m_current = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TASKING_EXPORT BarrierTaskAdapter : public Tasking::TaskAdapter<Barrier>
|
class TASKING_EXPORT BarrierTaskAdapter : public TaskAdapter<Barrier>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BarrierTaskAdapter() { connect(task(), &Barrier::done, this, &TaskInterface::done); }
|
BarrierTaskAdapter() { connect(task(), &Barrier::done, this, &TaskInterface::done); }
|
||||||
|
|||||||
100
src/libs/solutions/tasking/concurrentcall.h
Normal file
100
src/libs/solutions/tasking/concurrentcall.h
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tasking_global.h"
|
||||||
|
|
||||||
|
#include "tasktree.h"
|
||||||
|
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
|
namespace Tasking {
|
||||||
|
|
||||||
|
// This class introduces the dependency to Qt::Concurrent, otherwise Tasking namespace
|
||||||
|
// is independent on Qt::Concurrent.
|
||||||
|
// Possibly, it could be placed inside Qt::Concurrent library, as a wrapper around
|
||||||
|
// QtConcurrent::run() call.
|
||||||
|
|
||||||
|
template <typename ResultType>
|
||||||
|
class ConcurrentCall
|
||||||
|
{
|
||||||
|
Q_DISABLE_COPY_MOVE(ConcurrentCall)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ConcurrentCall() = default;
|
||||||
|
template <typename Function, typename ...Args>
|
||||||
|
void setConcurrentCallData(Function &&function, Args &&...args)
|
||||||
|
{
|
||||||
|
return wrapConcurrent(std::forward<Function>(function), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
void setThreadPool(QThreadPool *pool) { m_threadPool = pool; }
|
||||||
|
ResultType result() const
|
||||||
|
{
|
||||||
|
return m_future.resultCount() ? m_future.result() : ResultType();
|
||||||
|
}
|
||||||
|
QFuture<ResultType> future() const { return m_future; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename Function, typename ...Args>
|
||||||
|
void wrapConcurrent(Function &&function, Args &&...args)
|
||||||
|
{
|
||||||
|
m_startHandler = [=] {
|
||||||
|
if (m_threadPool)
|
||||||
|
return QtConcurrent::run(m_threadPool, function, args...);
|
||||||
|
return QtConcurrent::run(function, args...);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Function, typename ...Args>
|
||||||
|
void wrapConcurrent(std::reference_wrapper<const Function> &&wrapper, Args &&...args)
|
||||||
|
{
|
||||||
|
m_startHandler = [=] {
|
||||||
|
if (m_threadPool) {
|
||||||
|
return QtConcurrent::run(m_threadPool,
|
||||||
|
std::forward<const Function>(wrapper.get()), args...);
|
||||||
|
}
|
||||||
|
return QtConcurrent::run(std::forward<const Function>(wrapper.get()), args...);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
friend class ConcurrentCallTaskAdapter;
|
||||||
|
|
||||||
|
std::function<QFuture<ResultType>()> m_startHandler;
|
||||||
|
QThreadPool *m_threadPool = nullptr;
|
||||||
|
QFuture<ResultType> m_future;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ResultType>
|
||||||
|
class ConcurrentCallTaskAdapter : public TaskAdapter<ConcurrentCall<ResultType>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~ConcurrentCallTaskAdapter() {
|
||||||
|
if (m_watcher) {
|
||||||
|
m_watcher->cancel();
|
||||||
|
m_watcher->waitForFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
if (!this->task()->m_startHandler) {
|
||||||
|
emit this->done(false); // TODO: Add runtime assert
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_watcher.reset(new QFutureWatcher<ResultType>);
|
||||||
|
this->connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] {
|
||||||
|
emit this->done(!m_watcher->isCanceled());
|
||||||
|
m_watcher.release()->deleteLater();
|
||||||
|
});
|
||||||
|
this->task()->m_future = this->task()->m_startHandler();
|
||||||
|
m_watcher->setFuture(this->task()->m_future);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<QFutureWatcher<ResultType>> m_watcher;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Tasking
|
||||||
|
|
||||||
|
TASKING_DECLARE_TEMPLATE_TASK(ConcurrentCallTask, Tasking::ConcurrentCallTaskAdapter);
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
QtcLibrary {
|
QtcLibrary {
|
||||||
name: "Tasking"
|
name: "Tasking"
|
||||||
Depends { name: "Qt"; submodules: ["core"] }
|
Depends { name: "Qt"; submodules: ["concurrent", "core"] }
|
||||||
cpp.defines: base.concat("TASKING_LIBRARY")
|
cpp.defines: base.concat("TASKING_LIBRARY")
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
"barrier.cpp",
|
"barrier.cpp",
|
||||||
"barrier.h",
|
"barrier.h",
|
||||||
|
"concurrentcall.h",
|
||||||
"tasking_global.h",
|
"tasking_global.h",
|
||||||
"tasktree.cpp",
|
"tasktree.cpp",
|
||||||
"tasktree.h",
|
"tasktree.h",
|
||||||
|
|||||||
Reference in New Issue
Block a user