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 
46 QT_REQUIRE_CONFIG(future);
47 
48 QT_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 
60 namespace QtPrivate {
61 
62 class ResultItem
63 {
64 public:
ResultItem(const void * _result,int _count)65     ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results
ResultItem(const void * _result)66     ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
ResultItem()67     ResultItem() : m_count(0), result(nullptr) { }
isValid()68     bool isValid() const { return result != nullptr; }
isVector()69     bool isVector() const { return m_count != 0; }
count()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 
75 class Q_CORE_EXPORT ResultIteratorBase
76 {
77 public:
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;
90 protected:
91     QMap<int, ResultItem>::const_iterator mapIterator;
92     int m_vectorIndex;
93 public:
94     template <typename T>
value()95     const T &value() const
96     {
97         return *pointer<T>();
98     }
99 
100     template <typename T>
pointer()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 
110 class Q_CORE_EXPORT ResultStoreBase
111 {
112 public:
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 
126 protected:
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 
141 public:
142     template <typename T>
addResult(int index,const T * result)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>
addResults(int index,const QVector<T> * results)152     int addResults(int index, const QVector<T> *results)
153     {
154         return addResults(index, new QVector<T>(*results), results->count(), results->count());
155     }
156 
157     template <typename T>
addResults(int index,const QVector<T> * results,int totalCount)158     int addResults(int index, const QVector<T> *results, int totalCount)
159     {
160         if (m_filterMode == true && results->count() != totalCount && 0 == results->count())
161             return addResults(index, nullptr, 0, totalCount);
162         else
163             return addResults(index, new QVector<T>(*results), results->count(), totalCount);
164     }
165 
addCanceledResult(int index)166     int addCanceledResult(int index)
167     {
168         return addResult(index, static_cast<void *>(nullptr));
169     }
170 
171     template <typename T>
addCanceledResults(int index,int _count)172     int addCanceledResults(int index, int _count)
173     {
174         QVector<T> empty;
175         return addResults(index, &empty, _count);
176     }
177 
178     template <typename T>
clear()179     void clear()
180     {
181         QMap<int, ResultItem>::const_iterator mapIterator = m_results.constBegin();
182         while (mapIterator != m_results.constEnd()) {
183             if (mapIterator.value().isVector())
184                 delete reinterpret_cast<const QVector<T> *>(mapIterator.value().result);
185             else
186                 delete reinterpret_cast<const T *>(mapIterator.value().result);
187             ++mapIterator;
188         }
189         resultCount = 0;
190         m_results.clear();
191     }
192 };
193 
194 } // namespace QtPrivate
195 
196 Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE);
197 
198 
199 QT_END_NAMESPACE
200 
201 #endif
202