1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QTCORE_RESULTSTORE_H
5#define QTCORE_RESULTSTORE_H
6
7#include <QtCore/qmap.h>
8
9#include <utility>
10
11QT_REQUIRE_CONFIG(future);
12
13QT_BEGIN_NAMESPACE
14
15/*
16 ResultStore stores indexed results. Results can be added and retrieved
17 either individually batched in a QList. Retriveing results and checking
18 which indexes are in the store can be done either by iterating or by random
19 access. In addition results can be removed from the front of the store,
20 either individually or in batches.
21*/
22
23namespace QtPrivate {
24
25class ResultItem
26{
27public:
28 ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // construct with vector of results
29 ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
30 ResultItem() : m_count(0), result(nullptr) { }
31 bool isValid() const { return result != nullptr; }
32 bool isVector() const { return m_count != 0; }
33 int count() const { return (m_count == 0) ? 1 : m_count; }
34 int m_count; // result is either a pointer to a result or to a vector of results,
35 const void *result; // if count is 0 it's a result, otherwise it's a vector.
36};
37
38class Q_CORE_EXPORT ResultIteratorBase
39{
40public:
41 ResultIteratorBase();
42 ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex = 0);
43 int vectorIndex() const;
44 int resultIndex() const;
45
46 ResultIteratorBase operator++();
47 int batchSize() const;
48 void batchedAdvance();
49#if QT_CORE_REMOVED_SINCE(6, 8)
50 bool operator==(const ResultIteratorBase &other) const;
51 bool operator!=(const ResultIteratorBase &other) const;
52#endif
53 bool isVector() const;
54 bool canIncrementVectorIndex() const;
55 bool isValid() const;
56
57private:
58 friend bool comparesEqual(const ResultIteratorBase &lhs,
59 const ResultIteratorBase &rhs)
60 {
61 return (lhs.mapIterator == rhs.mapIterator && lhs.m_vectorIndex == rhs.m_vectorIndex);
62 }
63 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(ResultIteratorBase)
64protected:
65 QMap<int, ResultItem>::const_iterator mapIterator;
66 int m_vectorIndex;
67public:
68 template <typename T>
69 const T &value() const
70 {
71 return *pointer<T>();
72 }
73
74 template<typename T>
75 T &value()
76 {
77 return *pointer<T>();
78 }
79
80 template <typename T>
81 T *pointer()
82 {
83 const T *p = std::as_const(t&: *this).pointer<T>();
84 return const_cast<T *>(p);
85 }
86
87 template <typename T>
88 const T *pointer() const
89 {
90 if (mapIterator.value().isVector())
91 return &(reinterpret_cast<const QList<T> *>(mapIterator.value().result)->at(m_vectorIndex));
92 else
93 return reinterpret_cast<const T *>(mapIterator.value().result);
94 }
95};
96
97class Q_CORE_EXPORT ResultStoreBase final
98{
99public:
100 ResultStoreBase();
101 void setFilterMode(bool enable);
102 bool filterMode() const;
103 int addResult(int index, const void *result);
104 int addResults(int index, const void *results, int vectorSize, int logicalCount);
105 ResultIteratorBase begin() const;
106 ResultIteratorBase end() const;
107 bool hasNextResult() const;
108 ResultIteratorBase resultAt(int index) const;
109 bool contains(int index) const;
110 int count() const;
111 // ### Qt 7: 'virtual' isn't required, can be removed, along with renaming
112 // the class to ResultStore and changing the members below to be private.
113 virtual ~ResultStoreBase();
114
115protected:
116 int insertResultItem(int index, ResultItem &resultItem);
117 void insertResultItemIfValid(int index, ResultItem &resultItem);
118 bool containsValidResultItem(int index) const;
119 void syncPendingResults();
120 void syncResultCount();
121 int updateInsertIndex(int index, int _count);
122
123 QMap<int, ResultItem> m_results;
124 int insertIndex; // The index where the next results(s) will be inserted.
125 int resultCount; // The number of consecutive results stored, starting at index 0.
126
127 bool m_filterMode;
128 QMap<int, ResultItem> pendingResults;
129 int filteredResults;
130
131 template <typename T>
132 static void clear(QMap<int, ResultItem> &store)
133 {
134 QMap<int, ResultItem>::const_iterator mapIterator = store.constBegin();
135 while (mapIterator != store.constEnd()) {
136 if (mapIterator.value().isVector())
137 delete reinterpret_cast<const QList<T> *>(mapIterator.value().result);
138 else
139 delete reinterpret_cast<const T *>(mapIterator.value().result);
140 ++mapIterator;
141 }
142 store.clear();
143 }
144
145public:
146 template <typename T, typename...Args>
147 int emplaceResult(int index, Args&&...args)
148 {
149 if (containsValidResultItem(index)) // reject if already present
150 return -1;
151 return addResult(index, result: static_cast<void *>(new T(std::forward<Args>(args)...)));
152 }
153
154 template <typename T>
155 int addResult(int index, const T *result)
156 {
157 if (containsValidResultItem(index)) // reject if already present
158 return -1;
159
160 if (result == nullptr)
161 return addResult(index, result: static_cast<void *>(nullptr));
162
163 return addResult(index, result: static_cast<void *>(new T(*result)));
164 }
165
166 template <typename T>
167 int moveResult(int index, T &&result)
168 {
169 static_assert(!std::is_reference_v<T>, "trying to move from an lvalue!");
170
171 return emplaceResult<std::remove_cv_t<T>>(index, std::forward<T>(result));
172 }
173
174 template<typename T>
175 int addResults(int index, const QList<T> *results)
176 {
177 if (results->empty()) // reject if results are empty
178 return -1;
179
180 if (containsValidResultItem(index)) // reject if already present
181 return -1;
182
183 return addResults(index, new QList<T>(*results), results->size(), results->size());
184 }
185
186 template<typename T>
187 int addResults(int index, const QList<T> *results, int totalCount)
188 {
189 // reject if results are empty, and nothing is filtered away
190 if ((m_filterMode == false || results->size() == totalCount) && results->empty())
191 return -1;
192
193 if (containsValidResultItem(index)) // reject if already present
194 return -1;
195
196 if (m_filterMode == true && results->size() != totalCount && 0 == results->size())
197 return addResults(index, results: nullptr, vectorSize: 0, logicalCount: totalCount);
198
199 return addResults(index, new QList<T>(*results), results->size(), totalCount);
200 }
201
202 int addCanceledResult(int index)
203 {
204 if (containsValidResultItem(index)) // reject if already present
205 return -1;
206
207 return addResult(index, result: static_cast<void *>(nullptr));
208 }
209
210 template <typename T>
211 int addCanceledResults(int index, int _count)
212 {
213 if (containsValidResultItem(index)) // reject if already present
214 return -1;
215
216 QList<T> empty;
217 return addResults(index, &empty, _count);
218 }
219
220 template <typename T>
221 void clear()
222 {
223 ResultStoreBase::clear<T>(m_results);
224 resultCount = 0;
225 insertIndex = 0;
226 ResultStoreBase::clear<T>(pendingResults);
227 filteredResults = 0;
228 }
229};
230
231} // namespace QtPrivate
232
233Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE);
234
235
236QT_END_NAMESPACE
237
238#endif
239

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/corelib/thread/qresultstore.h