1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QTCORE_RESULTSTORE_H
41#define QTCORE_RESULTSTORE_H
42
43#include <QtCore/qmap.h>
44#include <QtCore/qdebug.h>
45
46QT_REQUIRE_CONFIG(future);
47
48QT_BEGIN_NAMESPACE
49
50
51/*
52 ResultStore stores indexed results. Results can be added and retrieved
53 either individually batched in a QVector. Retriveing results and checking
54 which indexes are in the store can be done either by iterating or by random
55 accees. In addition results kan be removed from the front of the store,
56 either individually or in batches.
57*/
58
59
60namespace QtPrivate {
61
62class ResultItem
63{
64public:
65 ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results
66 ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
67 ResultItem() : m_count(0), result(nullptr) { }
68 bool isValid() const { return result != nullptr; }
69 bool isVector() const { return m_count != 0; }
70 int count() const { return (m_count == 0) ? 1 : m_count; }
71 int m_count; // result is either a pointer to a result or to a vector of results,
72 const void *result; // if count is 0 it's a result, otherwise it's a vector.
73};
74
75class Q_CORE_EXPORT ResultIteratorBase
76{
77public:
78 ResultIteratorBase();
79 ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex = 0);
80 int vectorIndex() const;
81 int resultIndex() const;
82
83 ResultIteratorBase operator++();
84 int batchSize() const;
85 void batchedAdvance();
86 bool operator==(const ResultIteratorBase &other) const;
87 bool operator!=(const ResultIteratorBase &other) const;
88 bool isVector() const;
89 bool canIncrementVectorIndex() const;
90protected:
91 QMap<int, ResultItem>::const_iterator mapIterator;
92 int m_vectorIndex;
93public:
94 template <typename T>
95 const T &value() const
96 {
97 return *pointer<T>();
98 }
99
100 template <typename T>
101 const T *pointer() const
102 {
103 if (mapIterator.value().isVector())
104 return &(reinterpret_cast<const QVector<T> *>(mapIterator.value().result)->at(m_vectorIndex));
105 else
106 return reinterpret_cast<const T *>(mapIterator.value().result);
107 }
108};
109
110class Q_CORE_EXPORT ResultStoreBase
111{
112public:
113 ResultStoreBase();
114 void setFilterMode(bool enable);
115 bool filterMode() const;
116 int addResult(int index, const void *result);
117 int addResults(int index, const void *results, int vectorSize, int logicalCount);
118 ResultIteratorBase begin() const;
119 ResultIteratorBase end() const;
120 bool hasNextResult() const;
121 ResultIteratorBase resultAt(int index) const;
122 bool contains(int index) const;
123 int count() const;
124 virtual ~ResultStoreBase();
125
126protected:
127 int insertResultItem(int index, ResultItem &resultItem);
128 void insertResultItemIfValid(int index, ResultItem &resultItem);
129 void syncPendingResults();
130 void syncResultCount();
131 int updateInsertIndex(int index, int _count);
132
133 QMap<int, ResultItem> m_results;
134 int insertIndex; // The index where the next results(s) will be inserted.
135 int resultCount; // The number of consecutive results stored, starting at index 0.
136
137 bool m_filterMode;
138 QMap<int, ResultItem> pendingResults;
139 int filteredResults;
140
141public:
142 template <typename T>
143 int addResult(int index, const T *result)
144 {
145 if (result == nullptr)
146 return addResult(index, static_cast<void *>(nullptr));
147 else
148 return addResult(index, static_cast<void *>(new T(*result)));
149 }
150
151 template <typename T>
152 int addResults(int index, const QVector<T> *results)
153 {
154 if (results->empty()) // reject if results are empty
155 return -1;
156
157 return addResults(index, new QVector<T>(*results), results->count(), results->count());
158 }
159
160 template <typename T>
161 int addResults(int index, const QVector<T> *results, int totalCount)
162 {
163 // reject if results are empty, and nothing is filtered away
164 if ((m_filterMode == false || results->count() == totalCount) && results->empty())
165 return -1;
166
167 if (m_filterMode == true && results->count() != totalCount && 0 == results->count())
168 return addResults(index, nullptr, 0, totalCount);
169 else
170 return addResults(index, new QVector<T>(*results), results->count(), totalCount);
171 }
172
173 int addCanceledResult(int index)
174 {
175 return addResult(index, static_cast<void *>(nullptr));
176 }
177
178 template <typename T>
179 int addCanceledResults(int index, int _count)
180 {
181 QVector<T> empty;
182 return addResults(index, &empty, _count);
183 }
184
185 template <typename T>
186 void clear()
187 {
188 QMap<int, ResultItem>::const_iterator mapIterator = m_results.constBegin();
189 while (mapIterator != m_results.constEnd()) {
190 if (mapIterator.value().isVector())
191 delete reinterpret_cast<const QVector<T> *>(mapIterator.value().result);
192 else
193 delete reinterpret_cast<const T *>(mapIterator.value().result);
194 ++mapIterator;
195 }
196 resultCount = 0;
197 m_results.clear();
198 }
199};
200
201} // namespace QtPrivate
202
203Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE);
204
205
206QT_END_NAMESPACE
207
208#endif
209