42 #ifndef QTCONCURRENT_ITERATEKERNEL_H 43 #define QTCONCURRENT_ITERATEKERNEL_H 45 #include <QtCore/qglobal.h> 47 #ifndef QT_NO_CONCURRENT 49 #include <QtCore/qatomic.h> 50 #include <QtCore/qtconcurrentmedian.h> 51 #include <QtCore/qtconcurrentthreadengine.h> 69 template <
typename It,
typename T>
70 void advance(It &
it, T value)
88 void timeBeforeUser();
92 inline bool blockSizeMaxed()
94 return (m_blockSize >= maxBlockSize);
97 const int maxBlockSize;
100 Median<double> controlPartElapsed;
101 Median<double> userPartElapsed;
105 template <
typename T>
109 ResultReporter(ThreadEngine<T> *_threadEngine)
110 :threadEngine(_threadEngine)
115 void reserveSpace(
int resultCount)
117 currentResultCount = resultCount;
118 vector.resize(
qMax(resultCount, vector.count()));
121 void reportResults(
int begin)
123 const int useVectorThreshold = 4;
124 if (currentResultCount > useVectorThreshold) {
125 vector.resize(currentResultCount);
126 threadEngine->reportResults(vector, begin);
128 for (
int i = 0; i < currentResultCount; ++i)
129 threadEngine->reportResult(&vector.at(i), begin + i);
133 inline T * getPointer()
135 return vector.data();
138 int currentResultCount;
139 ThreadEngine<T> *threadEngine;
144 class ResultReporter<void>
147 inline ResultReporter(ThreadEngine<void> *) { }
148 inline void reserveSpace(
int) { };
149 inline void reportResults(
int) { };
150 inline void * getPointer() {
return 0; }
154 inline bool selectIteration(std::bidirectional_iterator_tag)
159 inline bool selectIteration(std::forward_iterator_tag)
164 inline bool selectIteration(std::random_access_iterator_tag)
170 template <
typename T>
171 inline bool selectIteration(T)
177 template <
typename Iterator,
typename T>
178 class IterateKernel :
public ThreadEngine<T>
181 typedef T ResultType;
183 IterateKernel(Iterator _begin, Iterator _end)
184 #if defined (QT_NO_STL) 185 : begin(_begin),
end(_end), current(_begin), currentIndex(0),
186 forIteration(
false), progressReportingEnabled(
true)
188 : begin(_begin),
end(_end), current(_begin), currentIndex(0),
189 forIteration(selectIteration(
typename std::iterator_traits<Iterator>::iterator_category())), progressReportingEnabled(
true)
192 #if defined (QT_NO_STL) 200 virtual ~IterateKernel() { }
202 virtual bool runIteration(Iterator
it,
int index , T *result)
204 virtual bool runIterations(Iterator _begin,
int beginIndex,
int endIndex, T *results)
209 progressReportingEnabled = this->isProgressReportingEnabled();
214 bool shouldStartThread()
217 return (currentIndex <
iterationCount) && !this->shouldThrottleThread();
219 return (iteratorThreads == 0);
222 ThreadFunctionResult threadFunction()
225 return this->forThreadFunction();
227 return this->whileThreadFunction();
230 ThreadFunctionResult forThreadFunction()
233 ResultReporter<T> resultReporter(
this);
236 if (this->isCanceled())
239 const int currentBlockSize = blockSizeManager.blockSize();
245 const int beginIndex = currentIndex.fetchAndAddRelease(currentBlockSize);
248 if (beginIndex >= endIndex) {
253 this->waitForResume();
255 if (shouldStartThread())
258 const int finalBlockSize = endIndex - beginIndex;
259 resultReporter.reserveSpace(finalBlockSize);
262 blockSizeManager.timeBeforeUser();
263 const bool resultsAvailable = this->runIterations(begin, beginIndex, endIndex, resultReporter.getPointer());
264 blockSizeManager.timeAfterUser();
266 if (resultsAvailable)
267 resultReporter.reportResults(beginIndex);
270 if (progressReportingEnabled) {
271 completed.fetchAndAddAcquire(finalBlockSize);
272 this->setProgressValue(this->completed);
275 if (this->shouldThrottleThread())
276 return ThrottleThread;
278 return ThreadFinished;
281 ThreadFunctionResult whileThreadFunction()
283 if (iteratorThreads.testAndSetAcquire(0, 1) ==
false)
284 return ThreadFinished;
286 ResultReporter<T> resultReporter(
this);
287 resultReporter.reserveSpace(1);
289 while (current !=
end) {
293 Iterator prev = current;
295 int index = currentIndex.fetchAndAddRelaxed(1);
296 iteratorThreads.testAndSetRelease(1, 0);
298 this->waitForResume();
300 if (shouldStartThread())
303 const bool resultAavailable = this->runIteration(prev, index, resultReporter.getPointer());
304 if (resultAavailable)
305 resultReporter.reportResults(index);
307 if (this->shouldThrottleThread())
308 return ThrottleThread;
310 if (iteratorThreads.testAndSetAcquire(0, 1) ==
false)
311 return ThreadFinished;
314 return ThreadFinished;
319 const Iterator begin;
327 bool progressReportingEnabled;
338 #endif // QT_NO_CONCURRENT
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
#define QT_END_NAMESPACE
This macro expands to.
The QAtomicInt class provides platform-independent atomic operations on integers. ...
#define it(className, varName)
The QVector class is a template class that provides a dynamic array.
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
#define QT_BEGIN_NAMESPACE
This macro expands to.
The QtConcurrent namespace provides high-level APIs that make it possible to write multi-threaded pro...
static const KeyPair *const end
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...