Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
concurrentcall.h
Go to the documentation of this file.
1// Copyright (C) 2024 Jarek Kobus
2// Copyright (C) 2024 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef TASKING_CONCURRENTCALL_H
6#define TASKING_CONCURRENTCALL_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include "tasktree.h"
20
21#include <QtConcurrent/QtConcurrent>
22
24
25namespace Tasking {
26
27// This class introduces the dependency to Qt::Concurrent, otherwise Tasking namespace
28// is independent on Qt::Concurrent.
29// Possibly, it could be placed inside Qt::Concurrent library, as a wrapper around
30// QtConcurrent::run() call.
31
32template <typename ResultType>
34{
35 Q_DISABLE_COPY_MOVE(ConcurrentCall)
36
37public:
38 ConcurrentCall() = default;
39 template <typename Function, typename ...Args>
40 void setConcurrentCallData(Function &&function, Args &&...args)
41 {
42 return wrapConcurrent(std::forward<Function>(function), std::forward<Args>(args)...);
43 }
44 void setThreadPool(QThreadPool *pool) { m_threadPool = pool; }
45 ResultType result() const
46 {
47 return m_future.resultCount() ? m_future.result() : ResultType();
48 }
49 QList<ResultType> results() const
50 {
51 return m_future.results();
52 }
53 QFuture<ResultType> future() const { return m_future; }
54
55private:
56 template <typename Function, typename ...Args>
57 void wrapConcurrent(Function &&function, Args &&...args)
58 {
59 m_startHandler = [this, function = std::forward<Function>(function), args...] {
60 QThreadPool *threadPool = m_threadPool ? m_threadPool : QThreadPool::globalInstance();
61 return QtConcurrent::run(threadPool, function, args...);
62 };
63 }
64
65 template <typename Function, typename ...Args>
66 void wrapConcurrent(std::reference_wrapper<const Function> &&wrapper, Args &&...args)
67 {
68 m_startHandler = [this, wrapper = std::forward<std::reference_wrapper<const Function>>(wrapper), args...] {
69 QThreadPool *threadPool = m_threadPool ? m_threadPool : QThreadPool::globalInstance();
70 return QtConcurrent::run(threadPool, std::forward<const Function>(wrapper.get()),
71 args...);
72 };
73 }
74
75 template <typename T>
77
78 std::function<QFuture<ResultType>()> m_startHandler;
79 QThreadPool *m_threadPool = nullptr;
80 QFuture<ResultType> m_future;
81};
82
83template <typename ResultType>
84class ConcurrentCallTaskAdapter : public TaskAdapter<ConcurrentCall<ResultType>>
85{
86public:
88 if (m_watcher) {
89 m_watcher->cancel();
90 m_watcher->waitForFinished();
91 }
92 }
93
94 void start() final {
95 if (!this->task()->m_startHandler) {
96 emit this->done(DoneResult::Error); // TODO: Add runtime assert
97 return;
98 }
99 m_watcher.reset(new QFutureWatcher<ResultType>);
100 this->connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] {
101 emit this->done(toDoneResult(!m_watcher->isCanceled()));
102 m_watcher.release()->deleteLater();
103 });
104 this->task()->m_future = this->task()->m_startHandler();
105 m_watcher->setFuture(this->task()->m_future);
106 }
107
108private:
109 std::unique_ptr<QFutureWatcher<ResultType>> m_watcher;
110};
111
112template <typename T>
113using ConcurrentCallTask = CustomTask<ConcurrentCallTaskAdapter<T>>;
114
115} // namespace Tasking
116
118
119#endif // TASKING_CONCURRENTCALL_H
int resultCount() const
Definition qfuture.h:97
QList< T > results() const
Definition qfuture.h:114
T result() const
Definition qfuture.h:309
\inmodule QtCore
Definition qthreadpool.h:22
static QThreadPool * globalInstance()
Returns the global QThreadPool instance.
void start() final
This method is called by the running TaskTree for starting the Task instance.
void setThreadPool(QThreadPool *pool)
QFuture< ResultType > future() const
QList< ResultType > results() const
ResultType result() const
void setConcurrentCallData(Function &&function, Args &&...args)
\inheaderfile solutions/tasking/tasktree.h \inmodule TaskingSolution
Definition tasktree.h:453
Combined button and popup list for selecting options.
QTCONCURRENT_RUN_NODISCARD auto run(QThreadPool *pool, Function &&f, Args &&...args)
\inmodule TaskingSolution
Definition barrier.cpp:9
CustomTask< ConcurrentCallTaskAdapter< T > > ConcurrentCallTask
#define emit
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QJSValueList args
void wrapper()