summaryrefslogtreecommitdiffstats
path: root/src/corelib/concurrent
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/corelib/concurrent
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/corelib/concurrent')
-rw-r--r--src/corelib/concurrent/concurrent.pri42
-rw-r--r--src/corelib/concurrent/qfuture.cpp697
-rw-r--r--src/corelib/concurrent/qfuture.h278
-rw-r--r--src/corelib/concurrent/qfutureinterface.cpp565
-rw-r--r--src/corelib/concurrent/qfutureinterface.h313
-rw-r--r--src/corelib/concurrent/qfutureinterface_p.h167
-rw-r--r--src/corelib/concurrent/qfuturesynchronizer.cpp156
-rw-r--r--src/corelib/concurrent/qfuturesynchronizer.h121
-rw-r--r--src/corelib/concurrent/qfuturewatcher.cpp592
-rw-r--r--src/corelib/concurrent/qfuturewatcher.h222
-rw-r--r--src/corelib/concurrent/qfuturewatcher_p.h90
-rw-r--r--src/corelib/concurrent/qrunnable.cpp107
-rw-r--r--src/corelib/concurrent/qrunnable.h73
-rw-r--r--src/corelib/concurrent/qtconcurrentcompilertest.h65
-rw-r--r--src/corelib/concurrent/qtconcurrentexception.cpp223
-rw-r--r--src/corelib/concurrent/qtconcurrentexception.h128
-rw-r--r--src/corelib/concurrent/qtconcurrentfilter.cpp330
-rw-r--r--src/corelib/concurrent/qtconcurrentfilter.h736
-rw-r--r--src/corelib/concurrent/qtconcurrentfilterkernel.h351
-rw-r--r--src/corelib/concurrent/qtconcurrentfunctionwrappers.h173
-rw-r--r--src/corelib/concurrent/qtconcurrentiteratekernel.cpp199
-rw-r--r--src/corelib/concurrent/qtconcurrentiteratekernel.h340
-rw-r--r--src/corelib/concurrent/qtconcurrentmap.cpp402
-rw-r--r--src/corelib/concurrent/qtconcurrentmap.h780
-rw-r--r--src/corelib/concurrent/qtconcurrentmapkernel.h273
-rw-r--r--src/corelib/concurrent/qtconcurrentmedian.h130
-rw-r--r--src/corelib/concurrent/qtconcurrentreducekernel.h255
-rw-r--r--src/corelib/concurrent/qtconcurrentresultstore.cpp256
-rw-r--r--src/corelib/concurrent/qtconcurrentresultstore.h239
-rw-r--r--src/corelib/concurrent/qtconcurrentrun.cpp152
-rw-r--r--src/corelib/concurrent/qtconcurrentrun.h297
-rw-r--r--src/corelib/concurrent/qtconcurrentrunbase.h155
-rw-r--r--src/corelib/concurrent/qtconcurrentstoredfunctioncall.h1328
-rw-r--r--src/corelib/concurrent/qtconcurrentthreadengine.cpp299
-rw-r--r--src/corelib/concurrent/qtconcurrentthreadengine.h285
-rw-r--r--src/corelib/concurrent/qthreadpool.cpp651
-rw-r--r--src/corelib/concurrent/qthreadpool.h96
-rw-r--r--src/corelib/concurrent/qthreadpool_p.h107
38 files changed, 11673 insertions, 0 deletions
diff --git a/src/corelib/concurrent/concurrent.pri b/src/corelib/concurrent/concurrent.pri
new file mode 100644
index 0000000000..940297139c
--- /dev/null
+++ b/src/corelib/concurrent/concurrent.pri
@@ -0,0 +1,42 @@
+SOURCES += \
+ concurrent/qfuture.cpp \
+ concurrent/qfutureinterface.cpp \
+ concurrent/qfuturesynchronizer.cpp \
+ concurrent/qfuturewatcher.cpp \
+ concurrent/qrunnable.cpp \
+ concurrent/qtconcurrentfilter.cpp \
+ concurrent/qtconcurrentmap.cpp \
+ concurrent/qtconcurrentresultstore.cpp \
+ concurrent/qtconcurrentthreadengine.cpp \
+ concurrent/qtconcurrentiteratekernel.cpp \
+ concurrent/qtconcurrentexception.cpp \
+ concurrent/qthreadpool.cpp
+
+HEADERS += \
+ concurrent/qfuture.h \
+ concurrent/qfutureinterface.h \
+ concurrent/qfuturesynchronizer.h \
+ concurrent/qfuturewatcher.h \
+ concurrent/qrunnable.h \
+ concurrent/qtconcurrentcompilertest.h \
+ concurrent/qtconcurrentexception.h \
+ concurrent/qtconcurrentfilter.h \
+ concurrent/qtconcurrentfilterkernel.h \
+ concurrent/qtconcurrentfunctionwrappers.h \
+ concurrent/qtconcurrentiteratekernel.h \
+ concurrent/qtconcurrentmap.h \
+ concurrent/qtconcurrentmapkernel.h \
+ concurrent/qtconcurrentmedian.h \
+ concurrent/qtconcurrentreducekernel.h \
+ concurrent/qtconcurrentresultstore.h \
+ concurrent/qtconcurrentrun.h \
+ concurrent/qtconcurrentrunbase.h \
+ concurrent/qtconcurrentstoredfunctioncall.h \
+ concurrent/qtconcurrentthreadengine.h \
+ concurrent/qthreadpool.h
+
+# private headers
+HEADERS += \
+ concurrent/qfutureinterface_p.h \
+ concurrent/qfuturewatcher_p.h \
+ concurrent/qthreadpool_p.h
diff --git a/src/corelib/concurrent/qfuture.cpp b/src/corelib/concurrent/qfuture.cpp
new file mode 100644
index 0000000000..dfae1de16e
--- /dev/null
+++ b/src/corelib/concurrent/qfuture.cpp
@@ -0,0 +1,697 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class QFuture
+ \threadsafe
+ \brief The QFuture class represents the result of an asynchronous computation.
+ \since 4.4
+
+ \ingroup thread
+
+ To start a computation, use one of the APIs in the
+ \l {Concurrent Programming}{Qt Concurrent} framework.
+
+ QFuture allows threads to be synchronized against one or more results
+ which will be ready at a later point in time. The result can be of any type
+ that has a default constructor and a copy constructor. If a result is not
+ available at the time of calling the result(), resultAt(), or results()
+ functions, QFuture will wait until the result becomes available. You can
+ use the isResultReadyAt() function to determine if a result is ready or
+ not. For QFuture objects that report more than one result, the
+ resultCount() function returns the number of continuous results. This
+ means that it is always safe to iterate through the results from 0 to
+ resultCount().
+
+ QFuture provides a \l{Java-style iterators}{Java-style iterator}
+ (QFutureIterator) and an \l{STL-style iterators}{STL-style iterator}
+ (QFuture::const_iterator). Using these iterators is another way to access
+ results in the future.
+
+ QFuture also offers ways to interact with a runnning computation. For
+ instance, the computation can be canceled with the cancel() function. To
+ pause the computation, use the setPaused() function or one of the pause(),
+ resume(), or togglePaused() convenience functions. Be aware that not all
+ asynchronous computations can be canceled or paused. For example, the
+ future returned by QtConcurrent::run() cannot be canceled; but the
+ future returned by QtConcurrent::mappedReduced() can.
+
+ Progress information is provided by the progressValue(),
+ progressMinimum(), progressMaximum(), and progressText() functions. The
+ waitForFinished() function causes the calling thread to block and wait for
+ the computation to finish, ensuring that all results are available.
+
+ The state of the computation represented by a QFuture can be queried using
+ the isCanceled(), isStarted(), isFinished(), isRunning(), or isPaused()
+ functions.
+
+ QFuture is a lightweight reference counted class that can be passed by
+ value.
+
+ QFuture<void> is specialized to not contain any of the result fetching
+ functions. Any QFuture<T> can be assigned or copied into a QFuture<void>
+ as well. This is useful if only status or progress information is needed
+ - not the actual result data.
+
+ To interact with running tasks using signals and slots, use QFutureWatcher.
+
+ \sa QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
+*/
+
+/*! \fn QFuture::QFuture()
+
+ Constructs an empty future.
+*/
+
+/*! \fn QFuture::QFuture(const QFuture &other)
+
+ Constructs a copy of \a other.
+
+ \sa operator=()
+*/
+
+/*! \fn QFuture::QFuture(QFutureInterface<T> *resultHolder)
+ \internal
+*/
+
+/*! \fn QFuture::~QFuture()
+
+ Destroys the future.
+
+ Note that this neither waits nor cancels the asynchronous computation. Use
+ waitForFinished() or QFutureSynchronizer when you need to ensure that the
+ computation is completed before the future is destroyed.
+*/
+
+/*! \fn QFuture &QFuture::operator=(const QFuture &other)
+
+ Assigns \a other to this future and returns a reference to this future.
+*/
+
+/*! \fn bool QFuture::operator==(const QFuture &other) const
+
+ Returns true if \a other is a copy of this future; otherwise returns false.
+*/
+
+/*! \fn bool QFuture::operator!=(const QFuture &other) const
+
+ Returns true if \a other is \e not a copy of this future; otherwise returns
+ false.
+*/
+
+/*! \fn void QFuture::cancel()
+
+ Cancels the asynchronous computation represented by this future. Note that
+ the cancelation is asynchronous. Use waitForFinished() after calling
+ cancel() when you need synchronous cancelation.
+
+ Results currently available may still be accessed on a canceled future,
+ but new results will \e not become available after calling this function.
+ Any QFutureWatcher object that is watching this future will not deliver
+ progress and result ready signals on a canceled future.
+
+ Be aware that not all asynchronous computations can be canceled. For
+ example, the future returned by QtConcurrent::run() cannot be canceled;
+ but the future returned by QtConcurrent::mappedReduced() can.
+*/
+
+/*! \fn bool QFuture::isCanceled() const
+
+ Returns true if the asynchronous computation has been canceled with the
+ cancel() function; otherwise returns false.
+
+ Be aware that the computation may still be running even though this
+ function returns true. See cancel() for more details.
+*/
+
+/*! \fn void QFuture::setPaused(bool paused)
+
+ If \a paused is true, this function pauses the asynchronous computation
+ represented by the future. If the computation is already paused, this
+ function does nothing. Any QFutureWatcher object that is watching this
+ future will stop delivering progress and result ready signals while the
+ future is paused. Signal delivery will continue once the future is
+ resumed.
+
+ If \a paused is false, this function resumes the asynchronous computation.
+ If the computation was not previously paused, this function does nothing.
+
+ Be aware that not all computations can be paused. For example, the future
+ returned by QtConcurrent::run() cannot be paused; but the future returned
+ by QtConcurrent::mappedReduced() can.
+
+ \sa pause(), resume(), togglePaused()
+*/
+
+/*! \fn bool QFuture::isPaused() const
+
+ Returns true if the asynchronous computation has been paused with the
+ pause() function; otherwise returns false.
+
+ Be aware that the computation may still be running even though this
+ function returns true. See setPaused() for more details.
+
+ \sa setPaused(), togglePaused()
+*/
+
+/*! \fn void QFuture::pause()
+
+ Pauses the asynchronous computation represented by this future. This is a
+ convenience method that simply calls setPaused(true).
+
+ \sa resume()
+*/
+
+/*! \fn void QFuture::resume()
+
+ Resumes the asynchronous computation represented by this future. This is a
+ convenience method that simply calls setPaused(false).
+
+ \sa pause()
+*/
+
+/*! \fn void QFuture::togglePaused()
+
+ Toggles the paused state of the asynchronous computation. In other words,
+ if the computation is currently paused, calling this function resumes it;
+ if the computation is running, it is paused. This is a convenience method
+ for calling setPaused(!isPaused()).
+
+ \sa setPaused(), pause(), resume()
+*/
+
+/*! \fn bool QFuture::isStarted() const
+
+ Returns true if the asynchronous computation represented by this future
+ has been started; otherwise returns false.
+*/
+
+/*! \fn bool QFuture::isFinished() const
+
+ Returns true if the asynchronous computation represented by this future
+ has finished; otherwise returns false.
+*/
+
+/*! \fn bool QFuture::isRunning() const
+
+ Returns true if the asynchronous computation represented by this future is
+ currently running; otherwise returns false.
+*/
+
+/*! \fn int QFuture::resultCount() const
+
+ Returns the number of continuous results available in this future. The real
+ number of results stored might be different from this value, due to gaps
+ in the result set. It is always safe to iterate through the results from 0
+ to resultCount().
+ \sa result(), resultAt(), results()
+*/
+
+/*! \fn int QFuture::progressValue() const
+
+ Returns the current progress value, which is between the progressMinimum()
+ and progressMaximum().
+
+ \sa progressMinimum(), progressMaximum()
+*/
+
+/*! \fn int QFuture::progressMinimum() const
+
+ Returns the minimum progressValue().
+
+ \sa progressValue(), progressMaximum()
+*/
+
+/*! \fn int QFuture::progressMaximum() const
+
+ Returns the maximum progressValue().
+
+ \sa progressValue(), progressMinimum()
+*/
+
+/*! \fn QString QFuture::progressText() const
+
+ Returns the (optional) textual representation of the progress as reported
+ by the asynchronous computation.
+
+ Be aware that not all computations provide a textual representation of the
+ progress, and as such, this function may return an empty string.
+*/
+
+/*! \fn void QFuture::waitForFinished()
+
+ Waits for the asynchronous computation to finish (including cancel()ed
+ computations).
+*/
+
+/*! \fn T QFuture::result() const
+
+ Returns the first result in the future. If the result is not immediately
+ available, this function will block and wait for the result to become
+ available. This is a convenience method for calling resultAt(0).
+
+ \sa resultAt(), results()
+*/
+
+/*! \fn T QFuture::resultAt(int index) const
+
+ Returns the result at \a index in the future. If the result is not
+ immediately available, this function will block and wait for the result to
+ become available.
+
+ \sa result(), results(), resultCount()
+*/
+
+/*! \fn bool QFuture::isResultReadyAt(int index) const
+
+ Returns true if the result at \a index is immediately available; otherwise
+ returns false.
+
+ \sa resultAt(), resultCount()
+*/
+
+/*! \fn QFuture::operator T() const
+
+ Returns the first result in the future. If the result is not immediately
+ available, this function will block and wait for the result to become
+ available. This is a convenience method for calling result() or
+ resultAt(0).
+
+ \sa result(), resultAt(), results()
+*/
+
+/*! \fn QList<T> QFuture::results() const
+
+ Returns all results from the future. If the results are not immediately
+ available, this function will block and wait for them to become available.
+
+ \sa result(), resultAt(), resultCount()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::begin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first result in the
+ future.
+
+ \sa constBegin(), end()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::end() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary result
+ after the last result in the future.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::constBegin() const
+
+ Returns a const \l{STL-style iterator} pointing to the first result in the
+ future.
+
+ \sa begin(), constEnd()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::constEnd() const
+
+ Returns a const \l{STL-style iterator} pointing to the imaginary result
+ after the last result in the future.
+
+ \sa constBegin(), end()
+*/
+
+/*! \class QFuture::const_iterator
+ \reentrant
+ \since 4.4
+
+ \brief The QFuture::const_iterator class provides an STL-style const
+ iterator for QFuture.
+
+ QFuture provides both \l{STL-style iterators} and \l{Java-style iterators}.
+ The STL-style iterators are more low-level and more cumbersome to use; on
+ the other hand, they are slightly faster and, for developers who already
+ know STL, have the advantage of familiarity.
+
+ The default QFuture::const_iterator constructor creates an uninitialized
+ iterator. You must initialize it using a QFuture function like
+ QFuture::constBegin() or QFuture::constEnd() before you start iterating.
+ Here's a typical loop that prints all the results available in a future:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuture.cpp 0
+
+ \sa QFutureIterator, QFuture
+*/
+
+/*! \typedef QFuture::const_iterator::iterator_category
+
+ Typedef for std::bidirectional_iterator_tag. Provided for STL compatibility.
+*/
+
+/*! \typedef QFuture::const_iterator::difference_type
+
+ Typedef for ptrdiff_t. Provided for STL compatibility.
+*/
+
+/*! \typedef QFuture::const_iterator::value_type
+
+ Typedef for T. Provided for STL compatibility.
+*/
+
+/*! \typedef QFuture::const_iterator::pointer
+
+ Typedef for const T *. Provided for STL compatibility.
+*/
+
+/*! \typedef QFuture::const_iterator::reference
+
+ Typedef for const T &. Provided for STL compatibility.
+*/
+
+/*! \fn QFuture::const_iterator::const_iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called on an
+ uninitialized iterartor. Use operator=() to assign a value to it before
+ using it.
+
+ \sa QFuture::constBegin() QFuture::constEnd()
+*/
+
+/*! \fn QFuture::const_iterator::const_iterator(QFuture const * const future, int index)
+ \internal
+*/
+
+/*! \fn QFuture::const_iterator::const_iterator(const const_iterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator=(const const_iterator &other)
+
+ Assigns \a other to this iterator.
+*/
+
+/*! \fn const T &QFuture::const_iterator::operator*() const
+
+ Returns the current result.
+*/
+
+/*! \fn const T *QFuture::const_iterator::operator->() const
+
+ Returns a pointer to the current result.
+*/
+
+/*! \fn bool QFuture::const_iterator::operator!=(const const_iterator &other) const
+
+ Returns true if \a other points to a different result than this iterator;
+ otherwise returns false.
+
+ \sa operator==()
+*/
+
+/*! \fn bool QFuture::const_iterator::operator==(const const_iterator &other) const
+
+ Returns true if \a other points to the same result as this iterator;
+ otherwise returns false.
+
+ \sa operator!=()
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator++()
+
+ The prefix ++ operator (\c{++it}) advances the iterator to the next result
+ in the future and returns an iterator to the new current result.
+
+ Calling this function on QFuture::constEnd() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::const_iterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{it++}) advances the iterator to the next
+ result in the future and returns an iterator to the previously current
+ result.
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator--()
+
+ The prefix -- operator (\c{--it}) makes the preceding result current and
+ returns an iterator to the new current result.
+
+ Calling this function on QFuture::constBegin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::const_iterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{it--}) makes the preceding result current and
+ returns an iterator to the previously current result.
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator+=(int j)
+
+ Advances the iterator by \a j results. (If \a j is negative, the iterator
+ goes backward.)
+
+ \sa operator-=(), operator+()
+*/
+
+/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator-=(int j)
+
+ Makes the iterator go back by \a j results. (If \a j is negative, the
+ iterator goes forward.)
+
+ \sa operator+=(), operator-()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::const_iterator::operator+(int j) const
+
+ Returns an iterator to the results at \a j positions forward from this
+ iterator. (If \a j is negative, the iterator goes backward.)
+
+ \sa operator-(), operator+=()
+*/
+
+/*! \fn QFuture::const_iterator QFuture::const_iterator::operator-(int j) const
+
+ Returns an iterator to the result at \a j positions backward from this
+ iterator. (If \a j is negative, the iterator goes forward.)
+
+ \sa operator+(), operator-=()
+*/
+
+/*! \typedef QFuture::ConstIterator
+
+ Qt-style synonym for QFuture::const_iterator.
+*/
+
+/*!
+ \class QFutureIterator
+ \reentrant
+ \since 4.4
+ \inmodule QtCore
+
+ \brief The QFutureIterator class provides a Java-style const iterator for
+ QFuture.
+
+ QFuture has both \l{Java-style iterators} and \l{STL-style iterators}. The
+ Java-style iterators are more high-level and easier to use than the
+ STL-style iterators; on the other hand, they are slightly less efficient.
+
+ An alternative to using iterators is to use index positions. Some QFuture
+ member functions take an index as their first parameter, making it
+ possible to access results without using iterators.
+
+ QFutureIterator\<T\> allows you to iterate over a QFuture\<T\>. Note that
+ there is no mutable iterator for QFuture (unlike the other Java-style
+ iterators).
+
+ The QFutureIterator constructor takes a QFuture as its argument. After
+ construction, the iterator is located at the very beginning of the result
+ list (i.e. before the first result). Here's how to iterate over all the
+ results sequentially:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuture.cpp 1
+
+ The next() function returns the next result (waiting for it to become
+ available, if necessary) from the future and advances the iterator. Unlike
+ STL-style iterators, Java-style iterators point \e between results rather
+ than directly \e at results. The first call to next() advances the iterator
+ to the position between the first and second result, and returns the first
+ result; the second call to next() advances the iterator to the position
+ between the second and third result, and returns the second result; and
+ so on.
+
+ \img javaiterators1.png
+
+ Here's how to iterate over the elements in reverse order:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuture.cpp 2
+
+ If you want to find all occurrences of a particular value, use findNext()
+ or findPrevious() in a loop.
+
+ Multiple iterators can be used on the same future. If the future is
+ modified while a QFutureIterator is active, the QFutureIterator will
+ continue iterating over the original future, ignoring the modified copy.
+
+ \sa QFuture::const_iterator, QFuture
+*/
+
+/*!
+ \fn QFutureIterator::QFutureIterator(const QFuture<T> &future)
+
+ Constructs an iterator for traversing \a future. The iterator is set to be
+ at the front of the result list (before the first result).
+
+ \sa operator=()
+*/
+
+/*! \fn QFutureIterator &QFutureIterator::operator=(const QFuture<T> &future)
+
+ Makes the iterator operate on \a future. The iterator is set to be at the
+ front of the result list (before the first result).
+
+ \sa toFront(), toBack()
+*/
+
+/*! \fn void QFutureIterator::toFront()
+
+ Moves the iterator to the front of the result list (before the first
+ result).
+
+ \sa toBack(), next()
+*/
+
+/*! \fn void QFutureIterator::toBack()
+
+ Moves the iterator to the back of the result list (after the last result).
+
+ \sa toFront(), previous()
+*/
+
+/*! \fn bool QFutureIterator::hasNext() const
+
+ Returns true if there is at least one result ahead of the iterator, e.g.,
+ the iterator is \e not at the back of the result list; otherwise returns
+ false.
+
+ \sa hasPrevious(), next()
+*/
+
+/*! \fn const T &QFutureIterator::next()
+
+ Returns the next result and advances the iterator by one position.
+
+ Calling this function on an iterator located at the back of the result
+ list leads to undefined results.
+
+ \sa hasNext(), peekNext(), previous()
+*/
+
+/*! \fn const T &QFutureIterator::peekNext() const
+
+ Returns the next result without moving the iterator.
+
+ Calling this function on an iterator located at the back of the result
+ list leads to undefined results.
+
+ \sa hasNext(), next(), peekPrevious()
+*/
+
+/*! \fn bool QFutureIterator::hasPrevious() const
+
+ Returns true if there is at least one result ahead of the iterator, e.g.,
+ the iterator is \e not at the front of the result list; otherwise returns
+ false.
+
+ \sa hasNext(), previous()
+*/
+
+/*! \fn const T &QFutureIterator::previous()
+
+ Returns the previous result and moves the iterator back by one position.
+
+ Calling this function on an iterator located at the front of the result
+ list leads to undefined results.
+
+ \sa hasPrevious(), peekPrevious(), next()
+*/
+
+/*! \fn const T &QFutureIterator::peekPrevious() const
+
+ Returns the previous result without moving the iterator.
+
+ Calling this function on an iterator located at the front of the result
+ list leads to undefined results.
+
+ \sa hasPrevious(), previous(), peekNext()
+*/
+
+/*! \fn bool QFutureIterator::findNext(const T &value)
+
+ Searches for \a value starting from the current iterator position forward.
+ Returns true if \a value is found; otherwise returns false.
+
+ After the call, if \a value was found, the iterator is positioned just
+ after the matching result; otherwise, the iterator is positioned at the
+ back of the result list.
+
+ \sa findPrevious()
+*/
+
+/*! \fn bool QFutureIterator::findPrevious(const T &value)
+
+ Searches for \a value starting from the current iterator position
+ backward. Returns true if \a value is found; otherwise returns false.
+
+ After the call, if \a value was found, the iterator is positioned just
+ before the matching result; otherwise, the iterator is positioned at the
+ front of the result list.
+
+ \sa findNext()
+*/
diff --git a/src/corelib/concurrent/qfuture.h b/src/corelib/concurrent/qfuture.h
new file mode 100644
index 0000000000..e8a6e264b3
--- /dev/null
+++ b/src/corelib/concurrent/qfuture.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTURE_H
+#define QFUTURE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qfutureinterface.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qtconcurrentcompilertest.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T>
+class QFutureWatcher;
+template <>
+class QFutureWatcher<void>;
+
+template <typename T>
+class QFuture
+{
+public:
+ QFuture()
+ : d(QFutureInterface<T>::canceledResult())
+ { }
+ explicit QFuture(QFutureInterface<T> *p) // internal
+ : d(*p)
+ { }
+ QFuture(const QFuture &other)
+ : d(other.d)
+ { }
+ ~QFuture()
+ { }
+
+ inline QFuture &operator=(const QFuture &other);
+ bool operator==(const QFuture &other) const { return (d == other.d); }
+ bool operator!=(const QFuture &other) const { return (d != other.d); }
+
+ void cancel() { d.cancel(); }
+ bool isCanceled() const { return d.isCanceled(); }
+
+ void setPaused(bool paused) { d.setPaused(paused); }
+ bool isPaused() const { return d.isPaused(); }
+ void pause() { setPaused(true); }
+ void resume() { setPaused(false); }
+ void togglePaused() { d.togglePaused(); }
+
+ bool isStarted() const { return d.isStarted(); }
+ bool isFinished() const { return d.isFinished(); }
+ bool isRunning() const { return d.isRunning(); }
+
+ int resultCount() const { return d.resultCount(); }
+ int progressValue() const { return d.progressValue(); }
+ int progressMinimum() const { return d.progressMinimum(); }
+ int progressMaximum() const { return d.progressMaximum(); }
+ QString progressText() const { return d.progressText(); }
+ void waitForFinished() { d.waitForFinished(); }
+
+ inline T result() const;
+ inline T resultAt(int index) const;
+ bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
+
+ operator T() const { return result(); }
+ QList<T> results() const { return d.results(); }
+
+ class const_iterator
+ {
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef qptrdiff difference_type;
+ typedef T value_type;
+ typedef const T *pointer;
+ typedef const T &reference;
+
+ inline const_iterator() {}
+ inline const_iterator(QFuture const * const _future, int _index) : future(_future), index(_index) {}
+ inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
+ inline const_iterator &operator=(const const_iterator &o)
+ { future = o.future; index = o.index; return *this; }
+ inline const T &operator*() const { return future->d.resultReference(index); }
+ inline const T *operator->() const { return future->d.resultPointer(index); }
+
+ inline bool operator!=(const const_iterator &other) const
+ {
+ if (index == -1 && other.index == -1) // comparing end != end?
+ return false;
+ if (other.index == -1)
+ return (future->isRunning() || (index < future->resultCount()));
+ return (index != other.index);
+ }
+
+ inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
+ inline const_iterator &operator++() { ++index; return *this; }
+ inline const_iterator operator++(int) { const_iterator r = *this; ++index; return r; }
+ inline const_iterator &operator--() { --index; return *this; }
+ inline const_iterator operator--(int) { const_iterator r = *this; --index; return r; }
+ inline const_iterator operator+(int j) const { return const_iterator(future, index + j); }
+ inline const_iterator operator-(int j) const { return const_iterator(future, index - j); }
+ inline const_iterator &operator+=(int j) { index += j; return *this; }
+ inline const_iterator &operator-=(int j) { index -= j; return *this; }
+ private:
+ QFuture const * future;
+ int index;
+ };
+ friend class const_iterator;
+ typedef const_iterator ConstIterator;
+
+ const_iterator begin() const { return const_iterator(this, 0); }
+ const_iterator constBegin() const { return const_iterator(this, 0); }
+ const_iterator end() const { return const_iterator(this, -1); }
+ const_iterator constEnd() const { return const_iterator(this, -1); }
+
+private:
+ friend class QFutureWatcher<T>;
+
+public: // Warning: the d pointer is not documented and is considered private.
+ mutable QFutureInterface<T> d;
+};
+
+template <typename T>
+inline QFuture<T> &QFuture<T>::operator=(const QFuture<T> &other)
+{
+ d = other.d;
+ return *this;
+}
+
+template <typename T>
+inline T QFuture<T>::result() const
+{
+ d.waitForResult(0);
+ return d.resultReference(0);
+}
+
+template <typename T>
+inline T QFuture<T>::resultAt(int index) const
+{
+ d.waitForResult(index);
+ return d.resultReference(index);
+}
+
+template <typename T>
+inline QFuture<T> QFutureInterface<T>::future()
+{
+ return QFuture<T>(this);
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
+
+template <>
+class QFuture<void>
+{
+public:
+ QFuture()
+ : d(QFutureInterface<void>::canceledResult())
+ { }
+ explicit QFuture(QFutureInterfaceBase *p) // internal
+ : d(*p)
+ { }
+ QFuture(const QFuture &other)
+ : d(other.d)
+ { }
+ ~QFuture()
+ { }
+
+ QFuture &operator=(const QFuture &other);
+ bool operator==(const QFuture &other) const { return (d == other.d); }
+ bool operator!=(const QFuture &other) const { return (d != other.d); }
+
+#if !defined(Q_CC_XLC)
+ template <typename T>
+ QFuture(const QFuture<T> &other)
+ : d(other.d)
+ { }
+
+ template <typename T>
+ QFuture<void> &operator=(const QFuture<T> &other)
+ {
+ d = other.d;
+ return *this;
+ }
+#endif
+
+ void cancel() { d.cancel(); }
+ bool isCanceled() const { return d.isCanceled(); }
+
+ void setPaused(bool paused) { d.setPaused(paused); }
+ bool isPaused() const { return d.isPaused(); }
+ void pause() { setPaused(true); }
+ void resume() { setPaused(false); }
+ void togglePaused() { d.togglePaused(); }
+
+ bool isStarted() const { return d.isStarted(); }
+ bool isFinished() const { return d.isFinished(); }
+ bool isRunning() const { return d.isRunning(); }
+
+ int resultCount() const { return d.resultCount(); }
+ int progressValue() const { return d.progressValue(); }
+ int progressMinimum() const { return d.progressMinimum(); }
+ int progressMaximum() const { return d.progressMaximum(); }
+ QString progressText() const { return d.progressText(); }
+ void waitForFinished() { d.waitForFinished(); }
+
+private:
+ friend class QFutureWatcher<void>;
+
+#ifdef QFUTURE_TEST
+public:
+#endif
+ mutable QFutureInterfaceBase d;
+};
+
+inline QFuture<void> &QFuture<void>::operator=(const QFuture<void> &other)
+{
+ d = other.d;
+ return *this;
+}
+
+inline QFuture<void> QFutureInterface<void>::future()
+{
+ return QFuture<void>(this);
+}
+
+template <typename T>
+QFuture<void> qToVoidFuture(const QFuture<T> &future)
+{
+ return QFuture<void>(future.d);
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif // QFUTURE_H
diff --git a/src/corelib/concurrent/qfutureinterface.cpp b/src/corelib/concurrent/qfutureinterface.cpp
new file mode 100644
index 0000000000..c5bd802480
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface.cpp
@@ -0,0 +1,565 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// qfutureinterface.h included from qfuture.h
+#include "qfuture.h"
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qthreadpool.h>
+#include <private/qthreadpool_p.h>
+
+#include "qfutureinterface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ MaxProgressEmitsPerSecond = 25
+};
+
+QFutureInterfaceBase::QFutureInterfaceBase(State initialState)
+ : d(new QFutureInterfaceBasePrivate(initialState))
+{ }
+
+QFutureInterfaceBase::QFutureInterfaceBase(const QFutureInterfaceBase &other)
+ : d(other.d)
+{
+ d->refCount.ref();
+}
+
+QFutureInterfaceBase::~QFutureInterfaceBase()
+{
+ if (!d->refCount.deref())
+ delete d;
+}
+
+void QFutureInterfaceBase::cancel()
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (d->state & Canceled)
+ return;
+
+ d->state = State((d->state & ~Paused) | Canceled);
+ d->waitCondition.wakeAll();
+ d->pausedWaitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+}
+
+void QFutureInterfaceBase::setPaused(bool paused)
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (paused) {
+ d->state = State(d->state | Paused);
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Paused));
+ } else {
+ d->state = State(d->state & ~Paused);
+ d->pausedWaitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Resumed));
+ }
+}
+
+void QFutureInterfaceBase::togglePaused()
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (d->state & Paused) {
+ d->state = State(d->state & ~Paused);
+ d->pausedWaitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Resumed));
+ } else {
+ d->state = State(d->state | Paused);
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Paused));
+ }
+}
+
+void QFutureInterfaceBase::setThrottled(bool enable)
+{
+ // bail out if we are not changing the state
+ if ((enable && (d->state & Throttled)) || (!enable && !(d->state & Throttled)))
+ return;
+
+ // lock and change the state
+ QMutexLocker lock(&d->m_mutex);
+ if (enable) {
+ d->state = State(d->state | Throttled);
+ } else {
+ d->state = State(d->state & ~Throttled);
+ if (!(d->state & Paused))
+ d->pausedWaitCondition.wakeAll();
+ }
+}
+
+
+bool QFutureInterfaceBase::isRunning() const
+{
+ return queryState(Running);
+}
+
+bool QFutureInterfaceBase::isStarted() const
+{
+ return queryState(Started);
+}
+
+bool QFutureInterfaceBase::isCanceled() const
+{
+ return queryState(Canceled);
+}
+
+bool QFutureInterfaceBase::isFinished() const
+{
+ return queryState(Finished);
+}
+
+bool QFutureInterfaceBase::isPaused() const
+{
+ return queryState(Paused);
+}
+
+bool QFutureInterfaceBase::isThrottled() const
+{
+ return queryState(Throttled);
+}
+
+bool QFutureInterfaceBase::isResultReadyAt(int index) const
+{
+ QMutexLocker lock(&d->m_mutex);
+ return d->internal_isResultReadyAt(index);
+}
+
+bool QFutureInterfaceBase::waitForNextResult()
+{
+ QMutexLocker lock(&d->m_mutex);
+ return d->internal_waitForNextResult();
+}
+
+void QFutureInterfaceBase::waitForResume()
+{
+ // return early if possible to avoid taking the mutex lock.
+ if ((d->state & Paused) == false || (d->state & Canceled))
+ return;
+
+ QMutexLocker lock(&d->m_mutex);
+ if ((d->state & Paused) == false || (d->state & Canceled))
+ return;
+
+ // decrease active thread count since this thread will wait.
+ QThreadPool::globalInstance()->releaseThread();
+
+ d->pausedWaitCondition.wait(&d->m_mutex);
+
+ QThreadPool::globalInstance()->reserveThread();
+}
+
+int QFutureInterfaceBase::progressValue() const
+{
+ return d->m_progressValue;
+}
+
+int QFutureInterfaceBase::progressMinimum() const
+{
+ return d->m_progressMinimum;
+}
+
+int QFutureInterfaceBase::progressMaximum() const
+{
+ return d->m_progressMaximum;
+}
+
+int QFutureInterfaceBase::resultCount() const
+{
+ QMutexLocker lock(&d->m_mutex);
+ return d->internal_resultCount();
+}
+
+QString QFutureInterfaceBase::progressText() const
+{
+ QMutexLocker locker(&d->m_mutex);
+ return d->m_progressText;
+}
+
+bool QFutureInterfaceBase::isProgressUpdateNeeded() const
+{
+ QMutexLocker locker(&d->m_mutex);
+ return !d->progressTime.isValid() || (d->progressTime.elapsed() > (1000 / MaxProgressEmitsPerSecond));
+}
+
+void QFutureInterfaceBase::reportStarted()
+{
+ QMutexLocker locker(&d->m_mutex);
+ if ((d->state & Started) || (d->state & Canceled) || (d->state & Finished))
+ return;
+
+ d->setState(State(Started | Running));
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Started));
+}
+
+void QFutureInterfaceBase::reportCanceled()
+{
+ cancel();
+}
+
+#ifndef QT_NO_EXCEPTIONS
+void QFutureInterfaceBase::reportException(const QtConcurrent::Exception &exception)
+{
+ QMutexLocker locker(&d->m_mutex);
+ if ((d->state & Canceled) || (d->state & Finished))
+ return;
+
+ d->m_exceptionStore.setException(exception);
+ d->state = State(d->state | Canceled);
+ d->waitCondition.wakeAll();
+ d->pausedWaitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+}
+#endif
+
+void QFutureInterfaceBase::reportFinished()
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (!(d->state & Finished)) {
+ d->state = State((d->state & ~Running) | Finished);
+ d->waitCondition.wakeAll();
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
+ }
+}
+
+void QFutureInterfaceBase::setExpectedResultCount(int resultCount)
+{
+ if (d->manualProgress == false)
+ setProgressRange(0, resultCount);
+ d->m_expectedResultCount = resultCount;
+}
+
+int QFutureInterfaceBase::expectedResultCount()
+{
+ return d->m_expectedResultCount;
+}
+
+bool QFutureInterfaceBase::queryState(State state) const
+{
+ return (d->state & state);
+}
+
+void QFutureInterfaceBase::waitForResult(int resultIndex)
+{
+ d->m_exceptionStore.throwPossibleException();
+
+ if (!(d->state & Running))
+ return;
+
+ // To avoid deadlocks and reduce the number of threads used, try to
+ // run the runnable in the current thread.
+ QThreadPool::globalInstance()->d_func()->stealRunnable(d->runnable);
+
+ QMutexLocker lock(&d->m_mutex);
+
+ if (!(d->state & Running))
+ return;
+
+ const int waitIndex = (resultIndex == -1) ? INT_MAX : resultIndex;
+ while ((d->state & Running) && d->internal_isResultReadyAt(waitIndex) == false)
+ d->waitCondition.wait(&d->m_mutex);
+
+ d->m_exceptionStore.throwPossibleException();
+}
+
+void QFutureInterfaceBase::waitForFinished()
+{
+ if (d->state & Running) {
+ QThreadPool::globalInstance()->d_func()->stealRunnable(d->runnable);
+
+ QMutexLocker lock(&d->m_mutex);
+
+ while (d->state & Running)
+ d->waitCondition.wait(&d->m_mutex);
+ }
+
+ d->m_exceptionStore.throwPossibleException();
+}
+
+void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
+{
+ if ((d->state & Canceled) || (d->state & Finished) || beginIndex == endIndex)
+ return;
+
+ d->waitCondition.wakeAll();
+
+ if (d->manualProgress == false) {
+ if (d->internal_updateProgress(d->m_progressValue + endIndex - beginIndex) == false) {
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
+ beginIndex,
+ endIndex));
+ return;
+ }
+
+ d->sendCallOuts(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
+ d->m_progressValue,
+ d->m_progressText),
+ QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
+ beginIndex,
+ endIndex));
+ return;
+ }
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady, beginIndex, endIndex));
+}
+
+void QFutureInterfaceBase::setRunnable(QRunnable *runnable)
+{
+ d->runnable = runnable;
+}
+
+void QFutureInterfaceBase::setFilterMode(bool enable)
+{
+ QMutexLocker locker(&d->m_mutex);
+ resultStoreBase().setFilterMode(enable);
+}
+
+void QFutureInterfaceBase::setProgressRange(int minimum, int maximum)
+{
+ QMutexLocker locker(&d->m_mutex);
+ d->m_progressMinimum = minimum;
+ d->m_progressMaximum = maximum;
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange, minimum, maximum));
+}
+
+void QFutureInterfaceBase::setProgressValue(int progressValue)
+{
+ setProgressValueAndText(progressValue, QString());
+}
+
+void QFutureInterfaceBase::setProgressValueAndText(int progressValue,
+ const QString &progressText)
+{
+ QMutexLocker locker(&d->m_mutex);
+ if (d->manualProgress == false)
+ d->manualProgress = true;
+ if (d->m_progressValue >= progressValue)
+ return;
+
+ if ((d->state & Canceled) || (d->state & Finished))
+ return;
+
+ if (d->internal_updateProgress(progressValue, progressText)) {
+ d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
+ d->m_progressValue,
+ d->m_progressText));
+ }
+}
+
+QMutex *QFutureInterfaceBase::mutex() const
+{
+ return &d->m_mutex;
+}
+
+QtConcurrent::internal::ExceptionStore &QFutureInterfaceBase::exceptionStore()
+{
+ return d->m_exceptionStore;
+}
+
+QtConcurrent::ResultStoreBase &QFutureInterfaceBase::resultStoreBase()
+{
+ return d->m_results;
+}
+
+const QtConcurrent::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() const
+{
+ return d->m_results;
+}
+
+QFutureInterfaceBase &QFutureInterfaceBase::operator=(const QFutureInterfaceBase &other)
+{
+ other.d->refCount.ref();
+ if (!d->refCount.deref())
+ delete d;
+ d = other.d;
+ return *this;
+}
+
+bool QFutureInterfaceBase::referenceCountIsOne() const
+{
+ return d->refCount == 1;
+}
+
+QFutureInterfaceBasePrivate::QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState)
+ : refCount(1), m_progressValue(0), m_progressMinimum(0), m_progressMaximum(0),
+ state(initialState), pendingResults(0),
+ manualProgress(false), m_expectedResultCount(0), runnable(0)
+{
+ progressTime.invalidate();
+}
+
+int QFutureInterfaceBasePrivate::internal_resultCount() const
+{
+ return m_results.count(); // ### subtract canceled results.
+}
+
+bool QFutureInterfaceBasePrivate::internal_isResultReadyAt(int index) const
+{
+ return (m_results.contains(index));
+}
+
+bool QFutureInterfaceBasePrivate::internal_waitForNextResult()
+{
+ if (m_results.hasNextResult())
+ return true;
+
+ while ((state & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
+ waitCondition.wait(&m_mutex);
+
+ return (!(state & QFutureInterfaceBase::Canceled) && m_results.hasNextResult());
+}
+
+bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
+ const QString &progressText)
+{
+ if (m_progressValue >= progress)
+ return false;
+
+ m_progressValue = progress;
+ m_progressText = progressText;
+
+ if (progressTime.isValid() && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted.
+ if (progressTime.elapsed() < (1000 / MaxProgressEmitsPerSecond))
+ return false;
+
+ progressTime.start();
+ return true;
+}
+
+void QFutureInterfaceBasePrivate::internal_setThrottled(bool enable)
+{
+ // bail out if we are not changing the state
+ if ((enable && (state & QFutureInterfaceBase::Throttled))
+ || (!enable && !(state & QFutureInterfaceBase::Throttled)))
+ return;
+
+ // change the state
+ if (enable) {
+ state = QFutureInterfaceBase::State(state | QFutureInterfaceBase::Throttled);
+ } else {
+ state = QFutureInterfaceBase::State(state & ~QFutureInterfaceBase::Throttled);
+ if (!(state & QFutureInterfaceBase::Paused))
+ pausedWaitCondition.wakeAll();
+ }
+}
+
+void QFutureInterfaceBasePrivate::sendCallOut(const QFutureCallOutEvent &callOutEvent)
+{
+ if (outputConnections.isEmpty())
+ return;
+
+ for (int i = 0; i < outputConnections.count(); ++i)
+ outputConnections.at(i)->postCallOutEvent(callOutEvent);
+}
+
+void QFutureInterfaceBasePrivate::sendCallOuts(const QFutureCallOutEvent &callOutEvent1,
+ const QFutureCallOutEvent &callOutEvent2)
+{
+ if (outputConnections.isEmpty())
+ return;
+
+ for (int i = 0; i < outputConnections.count(); ++i) {
+ QFutureCallOutInterface *interface = outputConnections.at(i);
+ interface->postCallOutEvent(callOutEvent1);
+ interface->postCallOutEvent(callOutEvent2);
+ }
+}
+
+// This function connects an output interface (for example a QFutureWatcher)
+// to this future. While holding the lock we check the state and ready results
+// and add the appropriate callouts to the queue. In order to avoid deadlocks,
+// the actual callouts are made at the end while not holding the lock.
+void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface *interface)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (state & QFutureInterfaceBase::Started) {
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Started));
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange,
+ m_progressMinimum,
+ m_progressMaximum));
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Progress,
+ m_progressValue,
+ m_progressText));
+ }
+
+ QtConcurrent::ResultIteratorBase it = m_results.begin();
+ while (it != m_results.end()) {
+ const int begin = it.resultIndex();
+ const int end = begin + it.batchSize();
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
+ begin,
+ end));
+ it.batchedAdvance();
+ }
+
+ if (state & QFutureInterfaceBase::Paused)
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Paused));
+
+ if (state & QFutureInterfaceBase::Canceled)
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
+
+ if (state & QFutureInterfaceBase::Finished)
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
+
+ outputConnections.append(interface);
+}
+
+void QFutureInterfaceBasePrivate::disconnectOutputInterface(QFutureCallOutInterface *interface)
+{
+ QMutexLocker lock(&m_mutex);
+ const int index = outputConnections.indexOf(interface);
+ if (index == -1)
+ return;
+ outputConnections.removeAt(index);
+
+ interface->callOutInterfaceDisconnected();
+}
+
+void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState)
+{
+ state = newState;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qfutureinterface.h b/src/corelib/concurrent/qfutureinterface.h
new file mode 100644
index 0000000000..7f90519a74
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTUREINTERFACE_H
+#define QFUTUREINTERFACE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qrunnable.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qtconcurrentexception.h>
+#include <QtCore/qtconcurrentresultstore.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T> class QFuture;
+class QFutureInterfaceBasePrivate;
+class QFutureWatcherBase;
+class QFutureWatcherBasePrivate;
+
+class Q_CORE_EXPORT QFutureInterfaceBase
+{
+public:
+ enum State {
+ NoState = 0x00,
+ Running = 0x01,
+ Started = 0x02,
+ Finished = 0x04,
+ Canceled = 0x08,
+ Paused = 0x10,
+ Throttled = 0x20
+ };
+
+ QFutureInterfaceBase(State initialState = NoState);
+ QFutureInterfaceBase(const QFutureInterfaceBase &other);
+ virtual ~QFutureInterfaceBase();
+
+ // reporting functions available to the engine author:
+ void reportStarted();
+ void reportFinished();
+ void reportCanceled();
+#ifndef QT_NO_EXCEPTIONS
+ void reportException(const QtConcurrent::Exception &e);
+#endif
+ void reportResultsReady(int beginIndex, int endIndex);
+
+ void setRunnable(QRunnable *runnable);
+ void setFilterMode(bool enable);
+ void setProgressRange(int minimum, int maximum);
+ int progressMinimum() const;
+ int progressMaximum() const;
+ bool isProgressUpdateNeeded() const;
+ void setProgressValue(int progressValue);
+ int progressValue() const;
+ void setProgressValueAndText(int progressValue, const QString &progressText);
+ QString progressText() const;
+
+ void setExpectedResultCount(int resultCount);
+ int expectedResultCount();
+ int resultCount() const;
+
+ bool queryState(State state) const;
+ bool isRunning() const;
+ bool isStarted() const;
+ bool isCanceled() const;
+ bool isFinished() const;
+ bool isPaused() const;
+ bool isThrottled() const;
+ bool isResultReadyAt(int index) const;
+
+ void cancel();
+ void setPaused(bool paused);
+ void togglePaused();
+ void setThrottled(bool enable);
+
+ void waitForFinished();
+ bool waitForNextResult();
+ void waitForResult(int resultIndex);
+ void waitForResume();
+
+ QMutex *mutex() const;
+ QtConcurrent::internal::ExceptionStore &exceptionStore();
+ QtConcurrent::ResultStoreBase &resultStoreBase();
+ const QtConcurrent::ResultStoreBase &resultStoreBase() const;
+
+ inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; }
+ inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; }
+ QFutureInterfaceBase &operator=(const QFutureInterfaceBase &other);
+
+protected:
+ bool referenceCountIsOne() const;
+public:
+
+#ifndef QFUTURE_TEST
+private:
+#endif
+ QFutureInterfaceBasePrivate *d;
+
+private:
+ friend class QFutureWatcherBase;
+ friend class QFutureWatcherBasePrivate;
+};
+
+template <typename T>
+class QFutureInterface : public QFutureInterfaceBase
+{
+public:
+ QFutureInterface(State initialState = NoState)
+ : QFutureInterfaceBase(initialState)
+ { }
+ QFutureInterface(const QFutureInterface &other)
+ : QFutureInterfaceBase(other)
+ { }
+ ~QFutureInterface()
+ {
+ if (referenceCountIsOne())
+ resultStore().clear();
+ }
+
+ static QFutureInterface canceledResult()
+ { return QFutureInterface(State(Started | Finished | Canceled)); }
+
+ QFutureInterface &operator=(const QFutureInterface &other)
+ {
+ if (referenceCountIsOne())
+ resultStore().clear();
+ QFutureInterfaceBase::operator=(other);
+ return *this;
+ }
+
+ inline QFuture<T> future(); // implemented in qfuture.h
+
+ inline void reportResult(const T *result, int index = -1);
+ inline void reportResult(const T &result, int index = -1);
+ inline void reportResults(const QVector<T> &results, int beginIndex = -1, int count = -1);
+ inline void reportFinished(const T *result = 0);
+
+ inline const T &resultReference(int index) const;
+ inline const T *resultPointer(int index) const;
+ inline QList<T> results();
+private:
+ QtConcurrent::ResultStore<T> &resultStore()
+ { return static_cast<QtConcurrent::ResultStore<T> &>(resultStoreBase()); }
+ const QtConcurrent::ResultStore<T> &resultStore() const
+ { return static_cast<const QtConcurrent::ResultStore<T> &>(resultStoreBase()); }
+};
+
+template <typename T>
+inline void QFutureInterface<T>::reportResult(const T *result, int index)
+{
+ QMutexLocker locker(mutex());
+ if (this->queryState(Canceled) || this->queryState(Finished)) {
+ return;
+ }
+
+ QtConcurrent::ResultStore<T> &store = resultStore();
+
+
+ if (store.filterMode()) {
+ const int resultCountBefore = store.count();
+ store.addResult(index, result);
+ this->reportResultsReady(resultCountBefore, resultCountBefore + store.count());
+ } else {
+ const int insertIndex = store.addResult(index, result);
+ this->reportResultsReady(insertIndex, insertIndex + 1);
+ }
+}
+
+template <typename T>
+inline void QFutureInterface<T>::reportResult(const T &result, int index)
+{
+ reportResult(&result, index);
+}
+
+template <typename T>
+inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count)
+{
+ QMutexLocker locker(mutex());
+ if (this->queryState(Canceled) || this->queryState(Finished)) {
+ return;
+ }
+
+ QtConcurrent::ResultStore<T> &store = resultStore();
+
+ if (store.filterMode()) {
+ const int resultCountBefore = store.count();
+ store.addResults(beginIndex, &_results, count);
+ this->reportResultsReady(resultCountBefore, store.count());
+ } else {
+ const int insertIndex = store.addResults(beginIndex, &_results, count);
+ this->reportResultsReady(insertIndex, insertIndex + _results.count());
+ }
+}
+
+template <typename T>
+inline void QFutureInterface<T>::reportFinished(const T *result)
+{
+ if (result)
+ reportResult(result);
+ QFutureInterfaceBase::reportFinished();
+}
+
+template <typename T>
+inline const T &QFutureInterface<T>::resultReference(int index) const
+{
+ QMutexLocker lock(mutex());
+ return resultStore().resultAt(index).value();
+}
+
+template <typename T>
+inline const T *QFutureInterface<T>::resultPointer(int index) const
+{
+ QMutexLocker lock(mutex());
+ return resultStore().resultAt(index).pointer();
+}
+
+template <typename T>
+inline QList<T> QFutureInterface<T>::results()
+{
+ if (this->isCanceled()) {
+ exceptionStore().throwPossibleException();
+ return QList<T>();
+ }
+ QFutureInterfaceBase::waitForResult(-1);
+
+ QList<T> res;
+ QMutexLocker lock(mutex());
+
+ QtConcurrent::ResultIterator<T> it = resultStore().begin();
+ while (it != resultStore().end()) {
+ res.append(it.value());
+ ++it;
+ }
+
+ return res;
+}
+
+template <>
+class QFutureInterface<void> : public QFutureInterfaceBase
+{
+public:
+ QFutureInterface<void>(State initialState = NoState)
+ : QFutureInterfaceBase(initialState)
+ { }
+ QFutureInterface<void>(const QFutureInterface<void> &other)
+ : QFutureInterfaceBase(other)
+ { }
+
+ static QFutureInterface<void> canceledResult()
+ { return QFutureInterface(State(Started | Finished | Canceled)); }
+
+ QFutureInterface<void> &operator=(const QFutureInterface<void> &other)
+ {
+ QFutureInterfaceBase::operator=(other);
+ return *this;
+ }
+
+ inline QFuture<void> future(); // implemented in qfuture.h
+
+ void reportResult(const void *, int) { }
+ void reportResults(const QVector<void> &, int) { }
+ void reportFinished(void * = 0) { QFutureInterfaceBase::reportFinished(); }
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif // QFUTUREINTERFACE_H
diff --git a/src/corelib/concurrent/qfutureinterface_p.h b/src/corelib/concurrent/qfutureinterface_p.h
new file mode 100644
index 0000000000..538947ead0
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface_p.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTUREINTERFACE_P_H
+#define QFUTUREINTERFACE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qrunnable.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFutureCallOutEvent : public QEvent
+{
+public:
+ enum CallOutType {
+ Started,
+ Finished,
+ Canceled,
+ Paused,
+ Resumed,
+ Progress,
+ ProgressRange,
+ ResultsReady
+ };
+
+ QFutureCallOutEvent()
+ : QEvent(QEvent::FutureCallOut), callOutType(CallOutType(0)), index1(-1), index2(-1)
+ { }
+ QFutureCallOutEvent(CallOutType callOutType, int index1 = -1)
+ : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(-1)
+ { }
+ QFutureCallOutEvent(CallOutType callOutType, int index1, int index2)
+ : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(index2)
+ { }
+
+ QFutureCallOutEvent(CallOutType callOutType, int index1, const QString &text)
+ : QEvent(QEvent::FutureCallOut),
+ callOutType(callOutType),
+ index1(index1),
+ index2(-1),
+ text(text)
+ { }
+
+ CallOutType callOutType;
+ int index1;
+ int index2;
+ QString text;
+
+ QFutureCallOutEvent *clone() const
+ {
+ return new QFutureCallOutEvent(callOutType, index1, index2, text);
+ }
+
+private:
+ QFutureCallOutEvent(CallOutType callOutType,
+ int index1,
+ int index2,
+ const QString &text)
+ : QEvent(QEvent::FutureCallOut),
+ callOutType(callOutType),
+ index1(index1),
+ index2(index2),
+ text(text)
+ { }
+};
+
+class QFutureCallOutInterface
+{
+public:
+ virtual ~QFutureCallOutInterface() {}
+ virtual void postCallOutEvent(const QFutureCallOutEvent &) = 0;
+ virtual void callOutInterfaceDisconnected() = 0;
+};
+
+class QFutureInterfaceBasePrivate
+{
+public:
+ QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState);
+
+ QAtomicInt refCount;
+ mutable QMutex m_mutex;
+ QWaitCondition waitCondition;
+ QList<QFutureCallOutInterface *> outputConnections;
+ int m_progressValue;
+ int m_progressMinimum;
+ int m_progressMaximum;
+ QFutureInterfaceBase::State state;
+ QElapsedTimer progressTime;
+ QWaitCondition pausedWaitCondition;
+ int pendingResults;
+ QtConcurrent::ResultStoreBase m_results;
+ bool manualProgress;
+ int m_expectedResultCount;
+ QtConcurrent::internal::ExceptionStore m_exceptionStore;
+ QString m_progressText;
+ QRunnable *runnable;
+
+ // Internal functions that does not change the mutex state.
+ // The mutex must be locked when calling these.
+ int internal_resultCount() const;
+ bool internal_isResultReadyAt(int index) const;
+ bool internal_waitForNextResult();
+ bool internal_updateProgress(int progress, const QString &progressText = QString());
+ void internal_setThrottled(bool enable);
+ void sendCallOut(const QFutureCallOutEvent &callOut);
+ void sendCallOuts(const QFutureCallOutEvent &callOut1, const QFutureCallOutEvent &callOut2);
+ void connectOutputInterface(QFutureCallOutInterface *iface);
+ void disconnectOutputInterface(QFutureCallOutInterface *iface);
+
+ void setState(QFutureInterfaceBase::State state);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/concurrent/qfuturesynchronizer.cpp b/src/corelib/concurrent/qfuturesynchronizer.cpp
new file mode 100644
index 0000000000..b52e5fb73d
--- /dev/null
+++ b/src/corelib/concurrent/qfuturesynchronizer.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class QFutureSynchronizer
+ \since 4.4
+
+ \brief The QFutureSynchronizer class is a convenience class that simplifies
+ QFuture synchronization.
+
+ \ingroup thread
+
+ QFutureSynchronizer is a template class that simplifies synchronization of
+ one or more QFuture objects. Futures are added using the addFuture() or
+ setFuture() functions. The futures() function returns a list of futures.
+ Use clearFutures() to remove all futures from the QFutureSynchronizer.
+
+ The waitForFinished() function waits for all futures to finish.
+ The destructor of QFutureSynchronizer calls waitForFinished(), providing
+ an easy way to ensure that all futures have finished before returning from
+ a function:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuturesynchronizer.cpp 0
+
+ The behavior of waitForFinished() can be changed using the
+ setCancelOnWait() function. Calling setCancelOnWait(true) will cause
+ waitForFinished() to cancel all futures before waiting for them to finish.
+ You can query the status of the cancel-on-wait feature using the
+ cancelOnWait() function.
+
+ \sa QFuture, QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
+*/
+
+/*!
+ \fn QFutureSynchronizer::QFutureSynchronizer()
+
+ Constructs a QFutureSynchronizer.
+*/
+
+/*!
+ \fn QFutureSynchronizer::QFutureSynchronizer(const QFuture<T> &future)
+
+ Constructs a QFutureSynchronizer and begins watching \a future by calling
+ addFuture().
+
+ \sa addFuture()
+*/
+
+/*!
+ \fn QFutureSynchronizer::~QFutureSynchronizer()
+
+ Calls waitForFinished() function to ensure that all futures have finished
+ before destroying this QFutureSynchronizer.
+
+ \sa waitForFinished()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::setFuture(const QFuture<T> &future)
+
+ Sets \a future to be the only future managed by this QFutureSynchronizer.
+ This is a convenience function that calls waitForFinished(),
+ then clearFutures(), and finally passes \a future to addFuture().
+
+ \sa addFuture(), waitForFinished(), clearFutures()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::addFuture(const QFuture<T> &future)
+
+ Adds \a future to the list of managed futures.
+
+ \sa futures()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::waitForFinished()
+
+ Waits for all futures to finish. If cancelOnWait() returns true, each
+ future is canceled before waiting for them to finish.
+
+ \sa cancelOnWait(), setCancelOnWait()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::clearFutures()
+
+ Removes all managed futures from this QFutureSynchronizer.
+
+ \sa addFuture(), setFuture()
+*/
+
+/*!
+ \fn QList<QFuture<T> > QFutureSynchronizer::futures() const
+
+ Returns a list of all managed futures.
+
+ \sa addFuture(), setFuture()
+*/
+
+/*!
+ \fn void QFutureSynchronizer::setCancelOnWait(bool enabled)
+
+ Enables or disables the cancel-on-wait feature based on the \a enabled
+ argument. If \a enabled is true, the waitForFinished() function will cancel
+ all futures before waiting for them to finish.
+
+ \sa waitForFinished()
+*/
+
+/*!
+ \fn bool QFutureSynchronizer::cancelOnWait() const
+
+ Returns true if the cancel-on-wait feature is enabled; otherwise returns
+ false. If cancel-on-wait is enabled, the waitForFinished() function will
+ cancel all futures before waiting for them to finish.
+
+ \sa waitForFinished()
+*/
diff --git a/src/corelib/concurrent/qfuturesynchronizer.h b/src/corelib/concurrent/qfuturesynchronizer.h
new file mode 100644
index 0000000000..23a2c242aa
--- /dev/null
+++ b/src/corelib/concurrent/qfuturesynchronizer.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTRUESYNCHRONIZER_H
+#define QFUTRUESYNCHRONIZER_H
+
+#include <QtCore/qfuture.h>
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T>
+class QFutureSynchronizer
+{
+ Q_DISABLE_COPY(QFutureSynchronizer)
+
+public:
+ QFutureSynchronizer() : m_cancelOnWait(false) { }
+ explicit QFutureSynchronizer(const QFuture<T> &future)
+ : m_cancelOnWait(false)
+ { addFuture(future); }
+ ~QFutureSynchronizer() { waitForFinished(); }
+
+ void setFuture(const QFuture<T> &future)
+ {
+ waitForFinished();
+ m_futures.clear();
+ addFuture(future);
+ }
+
+ void addFuture(const QFuture<T> &future)
+ {
+ m_futures.append(future);
+ }
+
+ void waitForFinished()
+ {
+ if (m_cancelOnWait) {
+ for (int i = 0; i < m_futures.count(); ++i) {
+ m_futures[i].cancel();
+ }
+ }
+
+ for (int i = 0; i < m_futures.count(); ++i) {
+ m_futures[i].waitForFinished();
+ }
+ }
+
+ void clearFutures()
+ {
+ m_futures.clear();
+ }
+
+ QList<QFuture<T> > futures() const
+ {
+ return m_futures;
+ }
+
+ void setCancelOnWait(bool enabled)
+ {
+ m_cancelOnWait = enabled;
+ }
+
+ bool cancelOnWait() const
+ {
+ return m_cancelOnWait;
+ }
+
+protected:
+ QList<QFuture<T> > m_futures;
+ bool m_cancelOnWait;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif // QFUTRUESYNCHRONIZER_H
diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp
new file mode 100644
index 0000000000..ea12bc9302
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher.cpp
@@ -0,0 +1,592 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfuturewatcher.h"
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qthread.h>
+
+#include "qfuturewatcher_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*! \class QFutureWatcher
+ \reentrant
+ \since 4.4
+
+ \ingroup thread
+
+ \brief The QFutureWatcher class allows monitoring a QFuture using signals
+ and slots.
+
+ QFutureWatcher provides information and notifications about a QFuture. Use
+ the setFuture() function to start watching a particular QFuture. The
+ future() function returns the future set with setFuture().
+
+ For convenience, several of QFuture's functions are also available in
+ QFutureWatcher: progressValue(), progressMinimum(), progressMaximum(),
+ progressText(), isStarted(), isFinished(), isRunning(), isCanceled(),
+ isPaused(), waitForFinished(), result(), and resultAt(). The cancel(),
+ setPaused(), pause(), resume(), and togglePaused() functions are slots in
+ QFutureWatcher.
+
+ Status changes are reported via the started(), finished(), canceled(),
+ paused(), resumed(), resultReadyAt(), and resultsReadyAt() signals.
+ Progress information is provided from the progressRangeChanged(),
+ void progressValueChanged(), and progressTextChanged() signals.
+
+ Throttling control is provided by the setPendingResultsLimit() function.
+ When the number of pending resultReadyAt() or resultsReadyAt() signals
+ exceeds the limit, the computation represented by the future will be
+ throttled automatically. The computation will resume once the number of
+ pending signals drops below the limit.
+
+ Example: Starting a computation and getting a slot callback when it's
+ finished:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qfuturewatcher.cpp 0
+
+ Be aware that not all asynchronous computations can be canceled or paused.
+ For example, the future returned by QtConcurrent::run() cannot be
+ canceled; but the future returned by QtConcurrent::mappedReduced() can.
+
+ QFutureWatcher<void> is specialized to not contain any of the result
+ fetching functions. Any QFuture<T> can be watched by a
+ QFutureWatcher<void> as well. This is useful if only status or progress
+ information is needed; not the actual result data.
+
+ \sa QFuture, {Concurrent Programming}{Qt Concurrent}
+*/
+
+/*! \fn QFutureWatcher::QFutureWatcher(QObject *parent)
+
+ Constructs a new QFutureWatcher with the given \a parent.
+*/
+QFutureWatcherBase::QFutureWatcherBase(QObject *parent)
+ :QObject(*new QFutureWatcherBasePrivate, parent)
+{ }
+
+/*! \fn QFutureWatcher::~QFutureWatcher()
+
+ Destroys the QFutureWatcher.
+*/
+
+/*! \fn void QFutureWatcher::cancel()
+
+ Cancels the asynchronous computation represented by the future(). Note that
+ the cancelation is asynchronous. Use waitForFinished() after calling
+ cancel() when you need synchronous cancelation.
+
+ Currently available results may still be accessed on a canceled QFuture,
+ but new results will \e not become available after calling this function.
+ Also, this QFutureWatcher will not deliver progress and result ready
+ signals once canceled. This includes the progressValueChanged(),
+ progressRangeChanged(), progressTextChanged(), resultReadyAt(), and
+ resultsReadyAt() signals.
+
+ Be aware that not all asynchronous computations can be canceled. For
+ example, the QFuture returned by QtConcurrent::run() cannot be canceled;
+ but the QFuture returned by QtConcurrent::mappedReduced() can.
+*/
+void QFutureWatcherBase::cancel()
+{
+ futureInterface().cancel();
+}
+
+/*! \fn void QFutureWatcher::setPaused(bool paused)
+
+ If \a paused is true, this function pauses the asynchronous computation
+ represented by the future(). If the computation is already paused, this
+ function does nothing. This QFutureWatcher will stop delivering progress
+ and result ready signals while the future is paused. Signal delivery will
+ continue once the computation is resumed.
+
+ If \a paused is false, this function resumes the asynchronous computation.
+ If the computation was not previously paused, this function does nothing.
+
+ Be aware that not all computations can be paused. For example, the
+ QFuture returned by QtConcurrent::run() cannot be paused; but the QFuture
+ returned by QtConcurrent::mappedReduced() can.
+
+ \sa pause(), resume(), togglePaused()
+*/
+void QFutureWatcherBase::setPaused(bool paused)
+{
+ futureInterface().setPaused(paused);
+}
+
+/*! \fn void QFutureWatcher::pause()
+
+ Pauses the asynchronous computation represented by the future(). This is a
+ convenience method that simply calls setPaused(true).
+
+ \sa resume()
+*/
+void QFutureWatcherBase::pause()
+{
+ futureInterface().setPaused(true);
+}
+
+/*! \fn void QFutureWatcher::resume()
+
+ Resumes the asynchronous computation represented by the future(). This is
+ a convenience method that simply calls setPaused(false).
+
+ \sa pause()
+*/
+void QFutureWatcherBase::resume()
+{
+ futureInterface().setPaused(false);
+}
+
+/*! \fn void QFutureWatcher::togglePaused()
+
+ Toggles the paused state of the asynchronous computation. In other words,
+ if the computation is currently paused, calling this function resumes it;
+ if the computation is running, it becomes paused. This is a convenience
+ method for calling setPaused(!isPaused()).
+
+ \sa setPaused(), pause(), resume()
+*/
+void QFutureWatcherBase::togglePaused()
+{
+ futureInterface().togglePaused();
+}
+
+/*! \fn int QFutureWatcher::progressValue() const
+
+ Returns the current progress value, which is between the progressMinimum()
+ and progressMaximum().
+
+ \sa progressMinimum(), progressMaximum()
+*/
+int QFutureWatcherBase::progressValue() const
+{
+ return futureInterface().progressValue();
+}
+
+/*! \fn int QFutureWatcher::progressMinimum() const
+
+ Returns the minimum progressValue().
+
+ \sa progressValue(), progressMaximum()
+*/
+int QFutureWatcherBase::progressMinimum() const
+{
+ return futureInterface().progressMinimum();
+}
+
+/*! \fn int QFutureWatcher::progressMaximum() const
+
+ Returns the maximum progressValue().
+
+ \sa progressValue(), progressMinimum()
+*/
+int QFutureWatcherBase::progressMaximum() const
+{
+ return futureInterface().progressMaximum();
+}
+
+/*! \fn QString QFutureWatcher::progressText() const
+
+ Returns the (optional) textual representation of the progress as reported
+ by the asynchronous computation.
+
+ Be aware that not all computations provide a textual representation of the
+ progress, and as such, this function may return an empty string.
+*/
+QString QFutureWatcherBase::progressText() const
+{
+ return futureInterface().progressText();
+}
+
+/*! \fn bool QFutureWatcher::isStarted() const
+
+ Returns true if the asynchronous computation represented by the future()
+ has been started; otherwise returns false.
+*/
+bool QFutureWatcherBase::isStarted() const
+{
+ return futureInterface().queryState(QFutureInterfaceBase::Started);
+}
+
+/*! \fn bool QFutureWatcher::isFinished() const
+
+ Returns true if the asynchronous computation represented by the future()
+ has finished; otherwise returns false.
+*/
+bool QFutureWatcherBase::isFinished() const
+{
+ Q_D(const QFutureWatcherBase);
+ return d->finished;
+}
+
+/*! \fn bool QFutureWatcher::isRunning() const
+
+ Returns true if the asynchronous computation represented by the future()
+ is currently running; otherwise returns false.
+*/
+bool QFutureWatcherBase::isRunning() const
+{
+ return futureInterface().queryState(QFutureInterfaceBase::Running);
+}
+
+/*! \fn bool QFutureWatcher::isCanceled() const
+
+ Returns true if the asynchronous computation has been canceled with the
+ cancel() function; otherwise returns false.
+
+ Be aware that the computation may still be running even though this
+ function returns true. See cancel() for more details.
+*/
+bool QFutureWatcherBase::isCanceled() const
+{
+ return futureInterface().queryState(QFutureInterfaceBase::Canceled);
+}
+
+/*! \fn bool QFutureWatcher::isPaused() const
+
+ Returns true if the asynchronous computation has been paused with the
+ pause() function; otherwise returns false.
+
+ Be aware that the computation may still be running even though this
+ function returns true. See setPaused() for more details.
+
+ \sa setPaused(), togglePaused()
+*/
+bool QFutureWatcherBase::isPaused() const
+{
+ return futureInterface().queryState(QFutureInterfaceBase::Paused);
+}
+
+/*! \fn void QFutureWatcher::waitForFinished()
+
+ Waits for the asynchronous computation to finish (including cancel()ed
+ computations).
+*/
+void QFutureWatcherBase::waitForFinished()
+{
+ futureInterface().waitForFinished();
+}
+
+/*! \fn void QFutureWatcher::setPendingResultsLimit(int limit)
+
+ The setPendingResultsLimit() provides throttling control. When the number
+ of pending resultReadyAt() or resultsReadyAt() signals exceeds the
+ \a limit, the computation represented by the future will be throttled
+ automatically. The computation will resume once the number of pending
+ signals drops below the \a limit.
+*/
+
+bool QFutureWatcherBase::event(QEvent *event)
+{
+ Q_D(QFutureWatcherBase);
+ if (event->type() == QEvent::FutureCallOut) {
+ QFutureCallOutEvent *callOutEvent = static_cast<QFutureCallOutEvent *>(event);
+
+ if (futureInterface().isPaused()) {
+ d->pendingCallOutEvents.append(callOutEvent->clone());
+ return true;
+ }
+
+ if (callOutEvent->callOutType == QFutureCallOutEvent::Resumed
+ && !d->pendingCallOutEvents.isEmpty()) {
+ // send the resume
+ d->sendCallOutEvent(callOutEvent);
+
+ // next send all pending call outs
+ for (int i = 0; i < d->pendingCallOutEvents.count(); ++i)
+ d->sendCallOutEvent(d->pendingCallOutEvents.at(i));
+ qDeleteAll(d->pendingCallOutEvents);
+ d->pendingCallOutEvents.clear();
+ } else {
+ d->sendCallOutEvent(callOutEvent);
+ }
+ return true;
+ }
+ return QObject::event(event);
+}
+
+void QFutureWatcherBase::setPendingResultsLimit(int limit)
+{
+ Q_D(QFutureWatcherBase);
+ d->maximumPendingResultsReady = limit;
+}
+
+void QFutureWatcherBase::connectNotify(const char * signal)
+{
+ Q_D(QFutureWatcherBase);
+ if (qstrcmp(signal, SIGNAL(resultReadyAt(int))) == 0)
+ d->resultAtConnected.ref();
+#ifndef QT_NO_DEBUG
+ if (qstrcmp(signal, SIGNAL(finished())) == 0) {
+ if (futureInterface().isRunning()) {
+ //connections should be established before calling stFuture to avoid race.
+ // (The future could finish before the connection is made.)
+ qWarning("QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race");
+ }
+ }
+#endif
+}
+
+void QFutureWatcherBase::disconnectNotify(const char * signal)
+{
+ Q_D(QFutureWatcherBase);
+ if (qstrcmp(signal, SIGNAL(resultReadyAt(int))) == 0)
+ d->resultAtConnected.deref();
+}
+
+/*!
+ \internal
+*/
+QFutureWatcherBasePrivate::QFutureWatcherBasePrivate()
+ : maximumPendingResultsReady(QThread::idealThreadCount() * 2),
+ resultAtConnected(0)
+{ }
+
+/*!
+ \internal
+*/
+void QFutureWatcherBase::connectOutputInterface()
+{
+ futureInterface().d->connectOutputInterface(d_func());
+}
+
+/*!
+ \internal
+*/
+void QFutureWatcherBase::disconnectOutputInterface(bool pendingAssignment)
+{
+ if (pendingAssignment) {
+ Q_D(QFutureWatcherBase);
+ d->pendingResultsReady = 0;
+ qDeleteAll(d->pendingCallOutEvents);
+ d->pendingCallOutEvents.clear();
+ d->finished = false;
+ }
+
+ futureInterface().d->disconnectOutputInterface(d_func());
+}
+
+void QFutureWatcherBasePrivate::postCallOutEvent(const QFutureCallOutEvent &callOutEvent)
+{
+ Q_Q(QFutureWatcherBase);
+
+ if (callOutEvent.callOutType == QFutureCallOutEvent::ResultsReady) {
+ if (pendingResultsReady.fetchAndAddRelaxed(1) >= maximumPendingResultsReady)
+ q->futureInterface().d->internal_setThrottled(true);
+ }
+
+ QCoreApplication::postEvent(q, callOutEvent.clone());
+}
+
+void QFutureWatcherBasePrivate::callOutInterfaceDisconnected()
+{
+ QCoreApplication::removePostedEvents(q_func(), QEvent::FutureCallOut);
+}
+
+void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
+{
+ Q_Q(QFutureWatcherBase);
+
+ switch (event->callOutType) {
+ case QFutureCallOutEvent::Started:
+ emit q->started();
+ break;
+ case QFutureCallOutEvent::Finished:
+ finished = true;
+ emit q->finished();
+ break;
+ case QFutureCallOutEvent::Canceled:
+ pendingResultsReady = 0;
+ emit q->canceled();
+ break;
+ case QFutureCallOutEvent::Paused:
+ if (q->futureInterface().isCanceled())
+ break;
+ emit q->paused();
+ break;
+ case QFutureCallOutEvent::Resumed:
+ if (q->futureInterface().isCanceled())
+ break;
+ emit q->resumed();
+ break;
+ case QFutureCallOutEvent::ResultsReady: {
+ if (q->futureInterface().isCanceled())
+ break;
+
+ if (pendingResultsReady.fetchAndAddRelaxed(-1) <= maximumPendingResultsReady)
+ q->futureInterface().setThrottled(false);
+
+ const int beginIndex = event->index1;
+ const int endIndex = event->index2;
+
+ emit q->resultsReadyAt(beginIndex, endIndex);
+
+ if (int(resultAtConnected) <= 0)
+ break;
+
+ for (int i = beginIndex; i < endIndex; ++i)
+ emit q->resultReadyAt(i);
+
+ } break;
+ case QFutureCallOutEvent::Progress:
+ if (q->futureInterface().isCanceled())
+ break;
+
+ emit q->progressValueChanged(event->index1);
+ if (!event->text.isNull()) // ###
+ q->progressTextChanged(event->text);
+ break;
+ case QFutureCallOutEvent::ProgressRange:
+ emit q->progressRangeChanged(event->index1, event->index2);
+ break;
+ default: break;
+ }
+}
+
+
+/*! \fn const T &QFutureWatcher::result() const
+
+ Returns the first result in the future(). If the result is not immediately
+ available, this function will block and wait for the result to become
+ available. This is a convenience method for calling resultAt(0).
+
+ \sa resultAt()
+*/
+
+/*! \fn const T &QFutureWatcher::resultAt(int index) const
+
+ Returns the result at \a index in the future(). If the result is not
+ immediately available, this function will block and wait for the result to
+ become available.
+
+ \sa result()
+*/
+
+/*! \fn void QFutureWatcher::setFuture(const QFuture<T> &future)
+
+ Starts watching the given \a future.
+
+ One of the signals might be emitted for the current state of the
+ \a future. For example, if the future is already stopped, the
+ finished signal will be emitted.
+
+ To avoid a race condition, it is important to call this function
+ \e after doing the connections.
+*/
+
+/*! \fn QFuture<T> QFutureWatcher::future() const
+
+ Returns the watched future.
+*/
+
+/*! \fn void QFutureWatcher::started()
+
+ This signal is emitted when this QFutureWatcher starts watching the future
+ set with setFuture().
+*/
+
+/*!
+ \fn void QFutureWatcher::finished()
+ This signal is emitted when the watched future finishes.
+*/
+
+/*!
+ \fn void QFutureWatcher::canceled()
+ This signal is emitted if the watched future is canceled.
+*/
+
+/*! \fn void QFutureWatcher::paused()
+ This signal is emitted when the watched future is paused.
+*/
+
+/*! \fn void QFutureWatcher::resumed()
+ This signal is emitted when the watched future is resumed.
+*/
+
+/*!
+ \fn void QFutureWatcher::progressRangeChanged(int minimum, int maximum)
+
+ The progress range for the watched future has changed to \a minimum and
+ \a maximum
+*/
+
+/*!
+ \fn void QFutureWatcher::progressValueChanged(int progressValue)
+
+ This signal is emitted when the watched future reports progress,
+ \a progressValue gives the current progress. In order to avoid overloading
+ the GUI event loop, QFutureWatcher limits the progress signal emission
+ rate. This means that listeners connected to this slot might not get all
+ progress reports the future makes. The last progress update (where
+ \a progressValue equals the maximum value) will always be delivered.
+*/
+
+/*! \fn void QFutureWatcher::progressTextChanged(const QString &progressText)
+
+ This signal is emitted when the watched future reports textual progress
+ information, \a progressText.
+*/
+
+/*!
+ \fn void QFutureWatcher::resultReadyAt(int index)
+
+ This signal is emitted when the watched future reports a ready result at
+ \a index. If the future reports multiple results, the index will indicate
+ which one it is. Results can be reported out-of-order. To get the result,
+ call future().result(index);
+*/
+
+/*!
+ \fn void QFutureWatcher::resultsReadyAt(int beginIndex, int endIndex);
+
+ This signal is emitted when the watched future reports ready results.
+ The results are indexed from \a beginIndex to \a endIndex.
+
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qfuturewatcher.h b/src/corelib/concurrent/qfuturewatcher.h
new file mode 100644
index 0000000000..5fe2007a01
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher.h
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTUREWATCHER_H
+#define QFUTUREWATCHER_H
+
+#include <QtCore/qfuture.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEvent;
+
+class QFutureWatcherBasePrivate;
+class Q_CORE_EXPORT QFutureWatcherBase : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFutureWatcherBase)
+
+public:
+ QFutureWatcherBase(QObject *parent = 0);
+
+ int progressValue() const;
+ int progressMinimum() const;
+ int progressMaximum() const;
+ QString progressText() const;
+
+ bool isStarted() const;
+ bool isFinished() const;
+ bool isRunning() const;
+ bool isCanceled() const;
+ bool isPaused() const;
+
+ void waitForFinished();
+
+ void setPendingResultsLimit(int limit);
+
+ bool event(QEvent *event);
+
+Q_SIGNALS:
+ void started();
+ void finished();
+ void canceled();
+ void paused();
+ void resumed();
+ void resultReadyAt(int resultIndex);
+ void resultsReadyAt(int beginIndex, int endIndex);
+ void progressRangeChanged(int minimum, int maximum);
+ void progressValueChanged(int progressValue);
+ void progressTextChanged(const QString &progressText);
+
+public Q_SLOTS:
+ void cancel();
+ void setPaused(bool paused);
+ void pause();
+ void resume();
+ void togglePaused();
+
+protected:
+ void connectNotify (const char * signal);
+ void disconnectNotify (const char * signal);
+
+ // called from setFuture() implemented in template sub-classes
+ void connectOutputInterface();
+ void disconnectOutputInterface(bool pendingAssignment = false);
+
+private:
+ // implemented in the template sub-classes
+ virtual const QFutureInterfaceBase &futureInterface() const = 0;
+ virtual QFutureInterfaceBase &futureInterface() = 0;
+};
+
+template <typename T>
+class QFutureWatcher : public QFutureWatcherBase
+{
+public:
+ QFutureWatcher(QObject *_parent = 0)
+ : QFutureWatcherBase(_parent)
+ { }
+ ~QFutureWatcher()
+ { disconnectOutputInterface(); }
+
+ void setFuture(const QFuture<T> &future);
+ QFuture<T> future() const
+ { return m_future; }
+
+ T result() const { return m_future.result(); }
+ T resultAt(int index) const { return m_future.resultAt(index); }
+
+#ifdef qdoc
+ int progressValue() const;
+ int progressMinimum() const;
+ int progressMaximum() const;
+ QString progressText() const;
+
+ bool isStarted() const;
+ bool isFinished() const;
+ bool isRunning() const;
+ bool isCanceled() const;
+ bool isPaused() const;
+
+ void waitForFinished();
+
+ void setPendingResultsLimit(int limit);
+
+Q_SIGNALS:
+ void started();
+ void finished();
+ void canceled();
+ void paused();
+ void resumed();
+ void resultReadyAt(int resultIndex);
+ void resultsReadyAt(int beginIndex, int endIndex);
+ void progressRangeChanged(int minimum, int maximum);
+ void progressValueChanged(int progressValue);
+ void progressTextChanged(const QString &progressText);
+
+public Q_SLOTS:
+ void cancel();
+ void setPaused(bool paused);
+ void pause();
+ void resume();
+ void togglePaused();
+#endif
+
+private:
+ QFuture<T> m_future;
+ const QFutureInterfaceBase &futureInterface() const { return m_future.d; }
+ QFutureInterfaceBase &futureInterface() { return m_future.d; }
+};
+
+template <typename T>
+Q_INLINE_TEMPLATE void QFutureWatcher<T>::setFuture(const QFuture<T> &_future)
+{
+ if (_future == m_future)
+ return;
+
+ disconnectOutputInterface(true);
+ m_future = _future;
+ connectOutputInterface();
+}
+
+template <>
+class QFutureWatcher<void> : public QFutureWatcherBase
+{
+public:
+ QFutureWatcher(QObject *_parent = 0)
+ : QFutureWatcherBase(_parent)
+ { }
+ ~QFutureWatcher()
+ { disconnectOutputInterface(); }
+
+ void setFuture(const QFuture<void> &future);
+ QFuture<void> future() const
+ { return m_future; }
+
+private:
+ QFuture<void> m_future;
+ const QFutureInterfaceBase &futureInterface() const { return m_future.d; }
+ QFutureInterfaceBase &futureInterface() { return m_future.d; }
+};
+
+Q_INLINE_TEMPLATE void QFutureWatcher<void>::setFuture(const QFuture<void> &_future)
+{
+ if (_future == m_future)
+ return;
+
+ disconnectOutputInterface(true);
+ m_future = _future;
+ connectOutputInterface();
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif // QFUTUREWATCHER_H
diff --git a/src/corelib/concurrent/qfuturewatcher_p.h b/src/corelib/concurrent/qfuturewatcher_p.h
new file mode 100644
index 0000000000..fd02d44773
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFUTUREWATCHER_P_H
+#define QFUTUREWATCHER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfutureinterface_p.h"
+#include <qlist.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFutureWatcherBase;
+class QFutureWatcherBasePrivate : public QObjectPrivate,
+ public QFutureCallOutInterface
+{
+ Q_DECLARE_PUBLIC(QFutureWatcherBase)
+
+public:
+ QFutureWatcherBasePrivate();
+
+ void postCallOutEvent(const QFutureCallOutEvent &callOutEvent);
+ void callOutInterfaceDisconnected();
+
+ void sendCallOutEvent(QFutureCallOutEvent *event);
+
+ QList<QFutureCallOutEvent *> pendingCallOutEvents;
+ QAtomicInt pendingResultsReady;
+ int maximumPendingResultsReady;
+
+ QAtomicInt resultAtConnected;
+ bool finished;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QFUTURE
+#endif
diff --git a/src/corelib/concurrent/qrunnable.cpp b/src/corelib/concurrent/qrunnable.cpp
new file mode 100644
index 0000000000..1aa7d59986
--- /dev/null
+++ b/src/corelib/concurrent/qrunnable.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QRunnable
+ \since 4.4
+ \brief The QRunnable class is the base class for all runnable objects.
+
+ \ingroup thread
+
+ The QRunnable class is an interface for representing a task or
+ piece of code that needs to be executed, represented by your
+ reimplementation of the run() function.
+
+ You can use QThreadPool to execute your code in a separate
+ thread. QThreadPool deletes the QRunnable automatically if
+ autoDelete() returns true (the default). Use setAutoDelete() to
+ change the auto-deletion flag.
+
+ QThreadPool supports executing the same QRunnable more than once
+ by calling QThreadPool::tryStart(this) from within the run() function.
+ If autoDelete is enabled the QRunnable will be deleted when
+ the last thread exits the run function. Calling QThreadPool::start()
+ multiple times with the same QRunnable when autoDelete is enabled
+ creates a race condition and is not recommended.
+
+ \sa QThreadPool
+*/
+
+/*! \fn QRunnable::run()
+ Implement this pure virtual function in your subclass.
+*/
+
+/*! \fn QRunnable::QRunnable()
+ Constructs a QRunnable. Auto-deletion is enabled by default.
+
+ \sa autoDelete(), setAutoDelete()
+*/
+
+/*! \fn QRunnable::~QRunnable()
+ QRunnable virtual destructor.
+*/
+
+/*! \fn bool QRunnable::autoDelete() const
+
+ Returns true is auto-deletion is enabled; false otherwise.
+
+ If auto-deletion is enabled, QThreadPool will automatically delete
+ this runnable after calling run(); otherwise, ownership remains
+ with the application programmer.
+
+ \sa setAutoDelete(), QThreadPool
+*/
+
+/*! \fn bool QRunnable::setAutoDelete(bool autoDelete)
+
+ Enables auto-deletion if \a autoDelete is true; otherwise
+ auto-deletion is disabled.
+
+ If auto-deletion is enabled, QThreadPool will automatically delete
+ this runnable after calling run(); otherwise, ownership remains
+ with the application programmer.
+
+ Note that this flag must be set before calling
+ QThreadPool::start(). Calling this function after
+ QThreadPool::start() results in undefined behavior.
+
+ \sa autoDelete(), QThreadPool
+*/
diff --git a/src/corelib/concurrent/qrunnable.h b/src/corelib/concurrent/qrunnable.h
new file mode 100644
index 0000000000..c4eea1184f
--- /dev/null
+++ b/src/corelib/concurrent/qrunnable.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRUNNABLE_H
+#define QRUNNABLE_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QRunnable
+{
+ int ref;
+
+ friend class QThreadPool;
+ friend class QThreadPoolPrivate;
+ friend class QThreadPoolThread;
+
+public:
+ virtual void run() = 0;
+
+ QRunnable() : ref(0) { }
+ virtual ~QRunnable() { }
+
+ bool autoDelete() const { return ref != -1; }
+ void setAutoDelete(bool _autoDelete) { ref = _autoDelete ? 0 : -1; }
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentcompilertest.h b/src/corelib/concurrent/qtconcurrentcompilertest.h
new file mode 100644
index 0000000000..fad0c35109
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentcompilertest.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_COMPILERTEST_H
+#define QTCONCURRENT_COMPILERTEST_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#if defined (Q_CC_MSVC) && (_MSC_VER < 1300)
+# define QT_TYPENAME
+#else
+# define QT_TYPENAME typename
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentexception.cpp b/src/corelib/concurrent/qtconcurrentexception.cpp
new file mode 100644
index 0000000000..b4123f52ca
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentexception.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentexception.h"
+
+#ifndef QT_NO_QFUTURE
+#ifndef QT_NO_EXCEPTIONS
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QtConcurrent::Exception
+ \brief The Exception class provides a base class for exceptions that can transferred across threads.
+ \since 4.4
+
+ Qt Concurrent supports throwing and catching exceptions across thread
+ boundaries, provided that the exception inherit from QtConcurrent::Exception
+ and implement two helper functions:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 0
+
+ QtConcurrent::Exception subclasses must be thrown by value and
+ caught by reference:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 1
+
+ If you throw an exception that is not a subclass of QtConcurrent::Exception,
+ the Qt Concurrent functions will throw a QtConcurrent::UnhandledException
+ in the receiver thread.
+
+ When using QFuture, transferred exceptions will be thrown when calling the following functions:
+ \list
+ \o QFuture::waitForFinished()
+ \o QFuture::result()
+ \o QFuture::resultAt()
+ \o QFuture::results()
+ \endlist
+*/
+
+/*!
+ \fn QtConcurrent::Exception::raise() const
+ In your QtConcurrent::Exception subclass, reimplement raise() like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 2
+*/
+
+/*!
+ \fn QtConcurrent::Exception::clone() const
+ In your QtConcurrent::Exception subclass, reimplement clone() like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 3
+*/
+
+/*!
+ \class QtConcurrent::UnhandledException
+
+ \brief The UnhandledException class represents an unhandled exception in a worker thread.
+ \since 4.4
+
+ If a worker thread throws an exception that is not a subclass of QtConcurrent::Exception,
+ the Qt Concurrent functions will throw a QtConcurrent::UnhandledException
+ on the receiver thread side.
+
+ Inheriting from this class is not supported.
+*/
+
+/*!
+ \fn QtConcurrent::UnhandledException::raise() const
+ \internal
+*/
+
+/*!
+ \fn QtConcurrent::UnhandledException::clone() const
+ \internal
+*/
+
+namespace QtConcurrent
+{
+
+void Exception::raise() const
+{
+ Exception e = *this;
+ throw e;
+}
+
+Exception *Exception::clone() const
+{
+ return new Exception(*this);
+}
+
+void UnhandledException::raise() const
+{
+ UnhandledException e = *this;
+ throw e;
+}
+
+Exception *UnhandledException::clone() const
+{
+ return new UnhandledException(*this);
+}
+
+#ifndef qdoc
+
+namespace internal {
+
+class Base
+{
+public:
+ Base(Exception *exception)
+ : exception(exception), refCount(1), hasThrown(false) { }
+ ~Base() { delete exception; }
+
+ Exception *exception;
+ QAtomicInt refCount;
+ bool hasThrown;
+};
+
+ExceptionHolder::ExceptionHolder(Exception *exception)
+: base(new Base(exception)) {}
+
+ExceptionHolder::ExceptionHolder(const ExceptionHolder &other)
+: base(other.base)
+{
+ base->refCount.ref();
+}
+
+void ExceptionHolder::operator=(const ExceptionHolder &other)
+{
+ if (base == other.base)
+ return;
+
+ if (base->refCount.deref() == false)
+ delete base;
+
+ base = other.base;
+ base->refCount.ref();
+}
+
+ExceptionHolder::~ExceptionHolder()
+{
+ if (base->refCount.deref() == 0)
+ delete base;
+}
+
+Exception *ExceptionHolder::exception() const
+{
+ return base->exception;
+}
+
+void ExceptionStore::setException(const Exception &e)
+{
+ if (hasException() == false)
+ exceptionHolder = ExceptionHolder(e.clone());
+}
+
+bool ExceptionStore::hasException() const
+{
+ return (exceptionHolder.exception() != 0);
+}
+
+ExceptionHolder ExceptionStore::exception()
+{
+ return exceptionHolder;
+}
+
+void ExceptionStore::throwPossibleException()
+{
+ if (hasException() ) {
+ exceptionHolder.base->hasThrown = true;
+ exceptionHolder.exception()->raise();
+ }
+}
+
+bool ExceptionStore::hasThrown() const { return exceptionHolder.base->hasThrown; }
+
+} // namespace internal
+
+#endif //qdoc
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_EXCEPTIONS
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qtconcurrentexception.h b/src/corelib/concurrent/qtconcurrentexception.h
new file mode 100644
index 0000000000..044b100e99
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentexception.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_EXCEPTION_H
+#define QTCONCURRENT_EXCEPTION_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qatomic.h>
+
+#ifndef QT_NO_EXCEPTIONS
+# include <exception>
+#endif
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+namespace QtConcurrent
+{
+
+#ifndef QT_NO_EXCEPTIONS
+
+class Q_CORE_EXPORT Exception : public std::exception
+{
+public:
+ virtual void raise() const;
+ virtual Exception *clone() const;
+};
+
+class Q_CORE_EXPORT UnhandledException : public Exception
+{
+public:
+ void raise() const;
+ Exception *clone() const;
+};
+
+namespace internal {
+
+class Base;
+class ExceptionHolder
+{
+public:
+ ExceptionHolder(Exception *exception = 0);
+ ExceptionHolder(const ExceptionHolder &other);
+ void operator=(const ExceptionHolder &other);
+ ~ExceptionHolder();
+ Exception *exception() const;
+ Base *base;
+};
+
+class Q_CORE_EXPORT ExceptionStore
+{
+public:
+ void setException(const Exception &e);
+ bool hasException() const;
+ ExceptionHolder exception();
+ void throwPossibleException();
+ bool hasThrown() const;
+ ExceptionHolder exceptionHolder;
+};
+
+} // namespace internal
+
+#else // QT_NO_EXCEPTIONS
+
+namespace internal {
+
+class Q_CORE_EXPORT ExceptionStore
+{
+public:
+ ExceptionStore() { }
+ inline void throwPossibleException() const {}
+};
+
+} // namespace internal
+
+#endif
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentfilter.cpp b/src/corelib/concurrent/qtconcurrentfilter.cpp
new file mode 100644
index 0000000000..6646e02afc
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilter.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtConcurrentFilter>
+ \title Concurrent Filter and Filter-Reduce
+ \ingroup thread
+
+ \brief The <QtConcurrentFilter> header provides concurrent Filter and
+ Filter-Reduce.
+
+ These functions are a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+
+ The QtConcurrent::filter(), QtConcurrent::filtered() and
+ QtConcurrent::filteredReduced() functions filter items in a sequence such
+ as a QList or a QVector in parallel. QtConcurrent::filter() modifies a
+ sequence in-place, QtConcurrent::filtered() returns a new sequence
+ containing the filtered content, and QtConcurrent::filteredReduced()
+ returns a single result.
+
+ Each of the above functions have a blocking variant that returns the final
+ result instead of a QFuture. You use them in the same way as the
+ asynchronous variants.
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 6
+
+ Note that the result types above are not QFuture objects, but real result
+ types (in this case, QStringList and QSet<QString>).
+
+ \section1 Concurrent Filter
+
+ QtConcurrent::filtered() takes an input sequence and a filter function.
+ This filter function is then called for each item in the sequence, and a
+ new sequence containing the filtered values is returned.
+
+ The filter function must be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 0
+
+ T must match the type stored in the sequence. The function returns true if
+ the item should be kept, false if it should be discarded.
+
+ This example shows how to keep strings that are all lower-case from a
+ QStringList:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 1
+
+ The results of the filter are made available through QFuture. See the
+ QFuture and QFutureWatcher documentation for more information on how to
+ use QFuture in your applications.
+
+ If you want to modify a sequence in-place, use QtConcurrent::filter():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 2
+
+ Since the sequence is modified in place, QtConcurrent::filter() does not
+ return any results via QFuture. However, you can still use QFuture and
+ QFutureWatcher to monitor the status of the filter.
+
+ \section1 Concurrent Filter-Reduce
+
+ QtConcurrent::filteredReduced() is similar to QtConcurrent::filtered(),
+ but instead of returing a sequence with the filtered results, the results
+ are combined into a single value using a reduce function.
+
+ The reduce function must be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 3
+
+ T is the type of the final result, U is the type of items being filtered.
+ Note that the return value and return type of the reduce function are not
+ used.
+
+ Call QtConcurrent::filteredReduced() like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 4
+
+ The reduce function will be called once for each result kept by the filter
+ function, and should merge the \e{intermediate} into the \e{result}
+ variable. QtConcurrent::filteredReduced() guarantees that only one thread
+ will call reduce at a time, so using a mutex to lock the result variable
+ is not necessary. The QtConcurrent::ReduceOptions enum provides a way to
+ control the order in which the reduction is done.
+
+ \section1 Additional API Features
+
+ \section2 Using Iterators instead of Sequence
+
+ Each of the above functions has a variant that takes an iterator range
+ instead of a sequence. You use them in the same way as the sequence
+ variants:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 5
+
+
+ \section2 Using Member Functions
+
+ QtConcurrent::filter(), QtConcurrent::filtered(), and
+ QtConcurrent::filteredReduced() accept pointers to member functions.
+ The member function class type must match the type stored in the sequence:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 7
+
+ Note that when using QtConcurrent::filteredReduced(), you can mix the use of
+ normal and member functions freely:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 8
+
+ \section2 Using Function Objects
+
+ QtConcurrent::filter(), QtConcurrent::filtered(), and
+ QtConcurrent::filteredReduced() accept function objects, which can be used to
+ add state to a function call. The result_type typedef must define the
+ result type of the function call operator:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 13
+
+ \section2 Using Bound Function Arguments
+
+ Note that Qt does not provide support for bound functions. This is
+ provided by 3rd party libraries like
+ \l{http://www.boost.org/libs/bind/bind.html}{Boost} or
+ \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf}
+ {C++ TR1 Library Extensions}.
+
+ If you want to use a filter function takes more than one argument, you can
+ use boost::bind() or std::tr1::bind() to transform it onto a function that
+ takes one argument.
+
+ As an example, we use QString::contains():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 9
+
+ QString::contains() takes 2 arguments (including the "this" pointer) and
+ can't be used with QtConcurrent::filtered() directly, because
+ QtConcurrent::filtered() expects a function that takes one argument. To
+ use QString::contains() with QtConcurrent::filtered() we have to provide a
+ value for the \e regexp argument:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 10
+
+ The return value from boost::bind() is a function object (functor) with
+ the following signature:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 11
+
+ This matches what QtConcurrent::filtered() expects, and the complete
+ example becomes:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentfilter.cpp 12
+*/
+
+/*!
+ \fn QFuture<void> QtConcurrent::filter(Sequence &sequence, FilterFunction filterFunction)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item in \a sequence. If
+ \a filterFunction returns true, the item is kept in \a sequence;
+ otherwise, the item is removed from \a sequence.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::filtered(const Sequence &sequence, FilterFunction filterFunction)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item in \a sequence and returns a
+ new Sequence of kept items. If \a filterFunction returns true, a copy of
+ the item is put in the new Sequence. Otherwise, the item will \e not
+ appear in the new Sequence.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::filtered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item from \a begin to \a end and
+ returns a new Sequence of kept items. If \a filterFunction returns true, a
+ copy of the item is put in the new Sequence. Otherwise, the item will
+ \e not appear in the new Sequence.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::filteredReduced(const Sequence &sequence, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item in \a sequence. If
+ \a filterFunction returns true for an item, that item is then passed to
+ \a reduceFunction. In other words, the return value is the result of
+ \a reduceFunction for each item where \a filterFunction returns true.
+
+ Note that while \a filterFunction is called concurrently, only one thread
+ at a time will call \a reduceFunction. The order in which \a reduceFunction
+ is called is undefined if \a reduceOptions is
+ QtConcurrent::UnorderedReduce. If \a reduceOptions is
+ QtConcurrent::OrderedReduce, \a reduceFunction is called in the order of
+ the original sequence.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::filteredReduced(ConstIterator begin, ConstIterator end, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+ \relates <QtConcurrentFilter>
+
+ Calls \a filterFunction once for each item from \a begin to \a end. If
+ \a filterFunction returns true for an item, that item is then passed to
+ \a reduceFunction. In other words, the return value is the result of
+ \a reduceFunction for each item where \a filterFunction returns true.
+
+ Note that while \a filterFunction is called concurrently, only one thread
+ at a time will call \a reduceFunction. The order in which
+ \a reduceFunction is called is undefined if \a reduceOptions is
+ QtConcurrent::UnorderedReduce. If \a reduceOptions is
+ QtConcurrent::OrderedReduce, the \a reduceFunction is called in the order
+ of the original sequence.
+*/
+
+/*!
+ \fn void QtConcurrent::blockingFilter(Sequence &sequence, FilterFunction filterFunction)
+
+ Calls \a filterFunction once for each item in \a sequence. If
+ \a filterFunction returns true, the item is kept in \a sequence;
+ otherwise, the item is removed from \a sequence.
+
+ \note This function will block until all items in the sequence have been processed.
+*/
+
+/*!
+ \fn Sequence QtConcurrent::blockingFiltered(const Sequence &sequence, FilterFunction filterFunction)
+
+ Calls \a filterFunction once for each item in \a sequence and returns a
+ new Sequence of kept items. If \a filterFunction returns true, a copy of
+ the item is put in the new Sequence. Otherwise, the item will \e not
+ appear in the new Sequence.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa filtered()
+*/
+
+/*!
+ \fn Sequence QtConcurrent::blockingFiltered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction)
+
+ Calls \a filterFunction once for each item from \a begin to \a end and
+ returns a new Sequence of kept items. If \a filterFunction returns true, a
+ copy of the item is put in the new Sequence. Otherwise, the item will
+ \e not appear in the new Sequence.
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa filtered()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingFilteredReduced(const Sequence &sequence, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+
+ Calls \a filterFunction once for each item in \a sequence. If
+ \a filterFunction returns true for an item, that item is then passed to
+ \a reduceFunction. In other words, the return value is the result of
+ \a reduceFunction for each item where \a filterFunction returns true.
+
+ Note that while \a filterFunction is called concurrently, only one thread
+ at a time will call \a reduceFunction. The order in which \a reduceFunction
+ is called is undefined if \a reduceOptions is
+ QtConcurrent::UnorderedReduce. If \a reduceOptions is
+ QtConcurrent::OrderedReduce, \a reduceFunction is called in the order of
+ the original sequence.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa filteredReduced()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingFilteredReduced(ConstIterator begin, ConstIterator end, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+
+ Calls \a filterFunction once for each item from \a begin to \a end. If
+ \a filterFunction returns true for an item, that item is then passed to
+ \a reduceFunction. In other words, the return value is the result of
+ \a reduceFunction for each item where \a filterFunction returns true.
+
+ Note that while \a filterFunction is called concurrently, only one thread
+ at a time will call \a reduceFunction. The order in which
+ \a reduceFunction is called is undefined if \a reduceOptions is
+ QtConcurrent::UnorderedReduce. If \a reduceOptions is
+ QtConcurrent::OrderedReduce, the \a reduceFunction is called in the order
+ of the original sequence.
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa filteredReduced()
+*/
diff --git a/src/corelib/concurrent/qtconcurrentfilter.h b/src/corelib/concurrent/qtconcurrentfilter.h
new file mode 100644
index 0000000000..e392212b12
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilter.h
@@ -0,0 +1,736 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_FILTER_H
+#define QTCONCURRENT_FILTER_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentfilterkernel.h>
+#include <QtCore/qtconcurrentfunctionwrappers.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifdef qdoc
+
+namespace QtConcurrent {
+
+ QFuture<void> filter(Sequence &sequence, FilterFunction filterFunction);
+
+ template <typename T>
+ QFuture<T> filtered(const Sequence &sequence, FilterFunction filterFunction);
+ template <typename T>
+ QFuture<T> filtered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction);
+
+ template <typename T>
+ QFuture<T> filteredReduced(const Sequence &sequence,
+ FilterFunction filterFunction,
+ ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce);
+ template <typename T>
+ QFuture<T> filteredReduced(ConstIterator begin,
+ ConstIterator end,
+ FilterFunction filterFunction,
+ ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce);
+
+ void blockingFilter(Sequence &sequence, FilterFunction filterFunction);
+
+ template <typename Sequence>
+ Sequence blockingFiltered(const Sequence &sequence, FilterFunction filterFunction);
+ template <typename Sequence>
+ Sequence blockingFiltered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction);
+
+ template <typename T>
+ T blockingFilteredReduced(const Sequence &sequence,
+ FilterFunction filterFunction,
+ ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce);
+ template <typename T>
+ T blockingFilteredReduced(ConstIterator begin,
+ ConstIterator end,
+ FilterFunction filterFunction,
+ ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce);
+
+} // namespace QtConcurrent
+
+#else
+
+namespace QtConcurrent {
+
+template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
+ThreadEngineStarter<void> filterInternal(Sequence &sequence, KeepFunctor keep, T (C::*reduce)(U))
+{
+ typedef MemberFunctionWrapper1<T, C, U> ReduceFunctor;
+ typedef typename Sequence::const_iterator Iterator;
+ typedef FilterKernel<Sequence, KeepFunctor, ReduceFunctor> KernelType;
+ return startThreadEngine(new KernelType(sequence, keep, reduce));
+}
+
+// filter() on sequences
+template <typename Sequence, typename KeepFunctor>
+QFuture<void> filter(Sequence &sequence, KeepFunctor keep)
+{
+ return filterInternal(sequence, keep, &Sequence::push_back);
+}
+
+template <typename Sequence, typename T>
+QFuture<void> filter(Sequence &sequence, bool (keep)(T))
+{
+ return filterInternal(sequence, FunctionWrapper1<bool, T>(keep), &Sequence::push_back);
+}
+
+template <typename Sequence, typename C>
+QFuture<void> filter(Sequence &sequence, bool (C::*keep)() const)
+{
+ return filterInternal(sequence, ConstMemberFunctionWrapper<bool, C>(keep), &Sequence::push_back);
+}
+
+// filteredReduced() on sequences
+template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startFilteredReduced<ResultType>(sequence, keep, reduce, options);
+ }
+
+template <typename ResultType, typename Sequence, typename T, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(const Sequence &sequence,
+ bool (filter)(T),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<ResultType>(sequence,
+ FunctionWrapper1<bool, T>(filter),
+ reduce,
+ options);
+}
+
+template <typename ResultType, typename Sequence, typename C, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(const Sequence &sequence,
+ bool (C::*filter)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<ResultType>(sequence,
+ ConstMemberFunctionWrapper<bool, C>(filter),
+ reduce,
+ options);
+}
+
+template <typename Sequence, typename KeepFunctor, typename T, typename U, typename V>
+QFuture<U> filteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<U>(sequence,
+ keep,
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
+QFuture<C> filteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<C>(sequence,
+ keep,
+ MemberFunctionWrapper1<T, C, U>(reduce),
+ options);
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename W>
+QFuture<V> filteredReduced(const Sequence &sequence,
+ bool (keep)(T),
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<V>(sequence,
+ FunctionWrapper1<bool, T>(keep),
+ FunctionWrapper2<U, V &, W>(reduce),
+ options);
+}
+
+template <typename Sequence, typename C, typename T, typename U, typename V>
+QFuture<U> filteredReduced(const Sequence &sequence,
+ bool (C::*keep)() const,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<U>(sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename T, typename U, typename C, typename V>
+QFuture<C> filteredReduced(const Sequence &sequence,
+ bool (keep)(T),
+ U (C::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<C>(sequence,
+ FunctionWrapper1<bool, T>(keep),
+ MemberFunctionWrapper1<U, C, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename C, typename T, typename D, typename U>
+QFuture<D> filteredReduced(const Sequence &sequence,
+ bool (C::*keep)() const,
+ T (D::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<D>(sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ MemberFunctionWrapper1<T, D, U>(reduce),
+ options);
+}
+
+// filteredReduced() on iterators
+template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startFilteredReduced<ResultType>(begin, end, keep, reduce, options);
+}
+
+template <typename ResultType, typename Iterator, typename T, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (filter)(T),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<ResultType>(begin,
+ end,
+ FunctionWrapper1<bool, T>(filter),
+ reduce,
+ options);
+}
+
+template <typename ResultType, typename Iterator, typename C, typename ReduceFunctor>
+QFuture<ResultType> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*filter)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<ResultType>(begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(filter),
+ reduce,
+ options);
+}
+
+template <typename Iterator, typename KeepFunctor, typename T, typename U, typename V>
+QFuture<U> filteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<U>(begin,
+ end,
+ keep,
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename KeepFunctor, typename T, typename C, typename U>
+QFuture<C> filteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<C>(begin,
+ end,
+ keep,
+ MemberFunctionWrapper1<T, C, U>(reduce),
+ options);
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename W>
+QFuture<V> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (keep)(T),
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<V>(begin,
+ end,
+ FunctionWrapper1<bool, T>(keep),
+ FunctionWrapper2<U, V &, W>(reduce),
+ options);
+}
+
+template <typename Iterator, typename C, typename T, typename U, typename V>
+QFuture<U> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<U>(begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename T, typename U, typename C, typename V>
+QFuture<C> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (keep)(T),
+ U (C::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<C>(begin,
+ end,
+ FunctionWrapper1<bool, T>(keep),
+ MemberFunctionWrapper1<U, C, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename C, typename T, typename D, typename U>
+QFuture<D> filteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const,
+ T (D::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return filteredReduced<D>(begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ MemberFunctionWrapper1<T, D, U>(reduce),
+ options);
+}
+
+
+// filtered() on sequences
+template <typename Sequence, typename KeepFunctor>
+QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, KeepFunctor keep)
+{
+ return startFiltered(sequence, keep);
+}
+
+template <typename Sequence, typename T>
+QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, bool (keep)(T))
+{
+ return startFiltered(sequence, FunctionWrapper1<bool, T>(keep));
+}
+
+template <typename Sequence, typename C>
+QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, bool (C::*keep)() const)
+{
+ return startFiltered(sequence, ConstMemberFunctionWrapper<bool, C>(keep));
+}
+
+// filtered() on iterators
+template <typename Iterator, typename KeepFunctor>
+QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, KeepFunctor keep)
+{
+ return startFiltered(begin, end, keep);
+}
+
+template <typename Iterator, typename T>
+QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, bool (keep)(T))
+{
+ return startFiltered(begin, end, FunctionWrapper1<bool, T>(keep));
+}
+
+template <typename Iterator, typename C>
+QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const)
+{
+ return startFiltered(begin, end, ConstMemberFunctionWrapper<bool, C>(keep));
+}
+
+
+// blocking filter() on sequences
+template <typename Sequence, typename KeepFunctor>
+void blockingFilter(Sequence &sequence, KeepFunctor keep)
+{
+ filterInternal(sequence, keep, &Sequence::push_back).startBlocking();
+}
+
+template <typename Sequence, typename T>
+void blockingFilter(Sequence &sequence, bool (keep)(T))
+{
+ filterInternal(sequence, FunctionWrapper1<bool, T>(keep), &Sequence::push_back)
+ .startBlocking();
+}
+
+template <typename Sequence, typename C>
+void blockingFilter(Sequence &sequence, bool (C::*keep)() const)
+{
+ filterInternal(sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ &Sequence::push_back)
+ .startBlocking();
+}
+
+// blocking filteredReduced() on sequences
+template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+ResultType blockingFilteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startFilteredReduced<ResultType>(sequence, keep, reduce, options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Sequence, typename T, typename ReduceFunctor>
+ResultType blockingFilteredReduced(const Sequence &sequence,
+ bool (filter)(T),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<ResultType>
+ (sequence,
+ FunctionWrapper1<bool, T>(filter),
+ reduce,
+ options);
+}
+
+template <typename ResultType, typename Sequence, typename C, typename ReduceFunctor>
+ResultType blockingFilteredReduced(const Sequence &sequence,
+ bool (C::*filter)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<ResultType>
+ (sequence,
+ ConstMemberFunctionWrapper<bool, C>(filter),
+ reduce,
+ options);
+}
+
+template <typename Sequence, typename KeepFunctor, typename T, typename U, typename V>
+U blockingFilteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<U>
+ (sequence,
+ keep,
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
+C blockingFilteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<C>
+ (sequence,
+ keep,
+ MemberFunctionWrapper1<T, C, U>(reduce),
+ options);
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename W>
+V blockingFilteredReduced(const Sequence &sequence,
+ bool (keep)(T),
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<V>
+ (sequence,
+ FunctionWrapper1<bool, T>(keep),
+ FunctionWrapper2<U, V &, W>(reduce),
+ options);
+}
+
+template <typename Sequence, typename C, typename T, typename U, typename V>
+U blockingFilteredReduced(const Sequence &sequence,
+ bool (C::*keep)() const,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<U>
+ (sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename T, typename U, typename C, typename V>
+C blockingFilteredReduced(const Sequence &sequence,
+ bool (keep)(T),
+ U (C::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<C>
+ (sequence,
+ FunctionWrapper1<bool, T>(keep),
+ MemberFunctionWrapper1<U, C, V>(reduce),
+ options);
+}
+
+template <typename Sequence, typename C, typename T, typename D, typename U>
+D blockingFilteredReduced(const Sequence &sequence,
+ bool (C::*keep)() const,
+ T (D::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<D>
+ (sequence,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ MemberFunctionWrapper1<T, D, U>(reduce),
+ options);
+}
+
+// blocking filteredReduced() on iterators
+template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor>
+ResultType blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startFilteredReduced<ResultType>(begin, end, keep, reduce, options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Iterator, typename T, typename ReduceFunctor>
+ResultType blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (filter)(T),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<ResultType>
+ (begin,
+ end,
+ FunctionWrapper1<bool, T>(filter),
+ reduce,
+ options);
+}
+
+template <typename ResultType, typename Iterator, typename C, typename ReduceFunctor>
+ResultType blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*filter)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<ResultType>
+ (begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(filter),
+ reduce,
+ options);
+}
+
+template <typename Iterator, typename KeepFunctor, typename T, typename U, typename V>
+U blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<U>
+ (begin,
+ end,
+ keep,
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename KeepFunctor, typename T, typename C, typename U>
+C blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ KeepFunctor keep,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<C>
+ (begin,
+ end,
+ keep,
+ MemberFunctionWrapper1<T, C, U>(reduce),
+ options);
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename W>
+V blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (keep)(T),
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<V>
+ (begin,
+ end,
+ FunctionWrapper1<bool, T>(keep),
+ FunctionWrapper2<U, V &, W>(reduce),
+ options);
+}
+
+template <typename Iterator, typename C, typename T, typename U, typename V>
+U blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<U>
+ (begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ FunctionWrapper2<T, U &, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename T, typename U, typename C, typename V>
+C blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (keep)(T),
+ U (C::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<C>
+ (begin,
+ end,
+ FunctionWrapper1<bool, T>(keep),
+ MemberFunctionWrapper1<U, C, V>(reduce),
+ options);
+}
+
+template <typename Iterator, typename C, typename T, typename D, typename U>
+D blockingFilteredReduced(Iterator begin,
+ Iterator end,
+ bool (C::*keep)() const,
+ T (D::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return blockingFilteredReduced<D>
+ (begin,
+ end,
+ ConstMemberFunctionWrapper<bool, C>(keep),
+ MemberFunctionWrapper1<T, D, U>(reduce),
+ options);
+}
+
+// blocking filtered() on sequences
+template <typename Sequence, typename KeepFunctor>
+Sequence blockingFiltered(const Sequence &sequence, KeepFunctor keep)
+{
+ return blockingFilteredReduced(sequence, keep, &Sequence::push_back, OrderedReduce);
+}
+
+template <typename Sequence, typename T>
+Sequence blockingFiltered(const Sequence &sequence, bool (keep)(T))
+{
+ return blockingFilteredReduced(sequence, keep, &Sequence::push_back, OrderedReduce);
+}
+
+template <typename Sequence, typename C>
+Sequence blockingFiltered(const Sequence &sequence, bool (C::*filter)() const)
+{
+ return blockingFilteredReduced(sequence,
+ filter,
+ &Sequence::push_back,
+ OrderedReduce);
+}
+
+// blocking filtered() on iterators
+template <typename OutputSequence, typename Iterator, typename KeepFunctor>
+OutputSequence blockingFiltered(Iterator begin, Iterator end, KeepFunctor keep)
+{
+ return blockingFilteredReduced(begin,
+ end,
+ keep,
+ &OutputSequence::push_back,
+ OrderedReduce);
+}
+
+template <typename OutputSequence, typename Iterator, typename T>
+OutputSequence blockingFiltered(Iterator begin, Iterator end, bool (keep)(T))
+{
+ return blockingFilteredReduced(begin,
+ end,
+ keep,
+ &OutputSequence::push_back,
+ OrderedReduce);
+}
+
+template <typename OutputSequence, typename Iterator, typename C>
+OutputSequence blockingFiltered(Iterator begin, Iterator end, bool (C::*filter)() const)
+{
+ return blockingFilteredReduced(begin,
+ end,
+ filter,
+ &OutputSequence::push_back,
+ OrderedReduce);
+}
+
+} // namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentfilterkernel.h b/src/corelib/concurrent/qtconcurrentfilterkernel.h
new file mode 100644
index 0000000000..cd926c006f
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilterkernel.h
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_FILTERKERNEL_H
+#define QTCONCURRENT_FILTERKERNEL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentiteratekernel.h>
+#include <QtCore/qtconcurrentmapkernel.h>
+#include <QtCore/qtconcurrentreducekernel.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+template <typename T>
+struct qValueType
+{
+ typedef typename T::value_type value_type;
+};
+
+template <typename T>
+struct qValueType<const T*>
+{
+ typedef T value_type;
+};
+
+template <typename T>
+struct qValueType<T*>
+{
+ typedef T value_type;
+};
+
+// Implementation of filter
+template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+class FilterKernel : public IterateKernel<typename Sequence::const_iterator, void>
+{
+ typedef ReduceKernel<ReduceFunctor, Sequence, typename Sequence::value_type> Reducer;
+ typedef IterateKernel<typename Sequence::const_iterator, void> IterateKernelType;
+ typedef typename ReduceFunctor::result_type T;
+
+ Sequence reducedResult;
+ Sequence &sequence;
+ KeepFunctor keep;
+ ReduceFunctor reduce;
+ Reducer reducer;
+
+public:
+ FilterKernel(Sequence &_sequence, KeepFunctor _keep, ReduceFunctor _reduce)
+ : IterateKernelType(const_cast<const Sequence &>(_sequence).begin(), const_cast<const Sequence &>(_sequence).end()), reducedResult(),
+ sequence(_sequence),
+ keep(_keep),
+ reduce(_reduce),
+ reducer(OrderedReduce)
+ { }
+
+ bool runIteration(typename Sequence::const_iterator it, int index, T *)
+ {
+ IntermediateResults<typename Sequence::value_type> results;
+ results.begin = index;
+ results.end = index + 1;
+
+ if (keep(*it))
+ results.vector.append(*it);
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ bool runIterations(typename Sequence::const_iterator sequenceBeginIterator, int begin, int end, T *)
+ {
+ IntermediateResults<typename Sequence::value_type> results;
+ results.begin = begin;
+ results.end = end;
+ results.vector.reserve(end - begin);
+
+
+ typename Sequence::const_iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ if (keep(*it))
+ results.vector.append(*it);
+ advance(it, 1);
+ }
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ void finish()
+ {
+ reducer.finish(reduce, reducedResult);
+ sequence = reducedResult;
+ }
+
+ inline bool shouldThrottleThread()
+ {
+ return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle();
+ }
+
+ inline bool shouldStartThread()
+ {
+ return IterateKernelType::shouldStartThread() && reducer.shouldStartThread();
+ }
+
+ typedef void ReturnType;
+ typedef void ResultType;
+};
+
+// Implementation of filter-reduce
+template <typename ReducedResultType,
+ typename Iterator,
+ typename KeepFunctor,
+ typename ReduceFunctor,
+ typename Reducer = ReduceKernel<ReduceFunctor,
+ ReducedResultType,
+ typename qValueType<Iterator>::value_type> >
+class FilteredReducedKernel : public IterateKernel<Iterator, ReducedResultType>
+{
+ ReducedResultType reducedResult;
+ KeepFunctor keep;
+ ReduceFunctor reduce;
+ Reducer reducer;
+ typedef IterateKernel<Iterator, ReducedResultType> IterateKernelType;
+
+public:
+ FilteredReducedKernel(Iterator begin,
+ Iterator end,
+ KeepFunctor _keep,
+ ReduceFunctor _reduce,
+ ReduceOptions reduceOption)
+ : IterateKernelType(begin, end), reducedResult(), keep(_keep), reduce(_reduce), reducer(reduceOption)
+ { }
+
+#if 0
+ FilteredReducedKernel(ReducedResultType initialValue,
+ KeepFunctor keep,
+ ReduceFunctor reduce,
+ ReduceOption reduceOption)
+ : reducedResult(initialValue), keep(keep), reduce(reduce), reducer(reduceOption)
+ { }
+#endif
+
+ bool runIteration(Iterator it, int index, ReducedResultType *)
+ {
+ IntermediateResults<typename qValueType<Iterator>::value_type> results;
+ results.begin = index;
+ results.end = index + 1;
+
+ if (keep(*it))
+ results.vector.append(*it);
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *)
+ {
+ IntermediateResults<typename qValueType<Iterator>::value_type> results;
+ results.begin = begin;
+ results.end = end;
+ results.vector.reserve(end - begin);
+
+ Iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ if (keep(*it))
+ results.vector.append(*it);
+ advance(it, 1);
+ }
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ void finish()
+ {
+ reducer.finish(reduce, reducedResult);
+ }
+
+ inline bool shouldThrottleThread()
+ {
+ return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle();
+ }
+
+ inline bool shouldStartThread()
+ {
+ return IterateKernelType::shouldStartThread() && reducer.shouldStartThread();
+ }
+
+ typedef ReducedResultType ReturnType;
+ typedef ReducedResultType ResultType;
+ ReducedResultType *result()
+ {
+ return &reducedResult;
+ }
+};
+
+// Implementation of filter that reports individual results via QFutureInterface
+template <typename Iterator, typename KeepFunctor>
+class FilteredEachKernel : public IterateKernel<Iterator, typename qValueType<Iterator>::value_type>
+{
+ typedef typename qValueType<Iterator>::value_type T;
+ typedef IterateKernel<Iterator, T> IterateKernelType;
+
+ KeepFunctor keep;
+
+public:
+ typedef T ReturnType;
+ typedef T ResultType;
+
+ FilteredEachKernel(Iterator begin, Iterator end, KeepFunctor _keep)
+ : IterateKernelType(begin, end), keep(_keep)
+ { }
+
+ void start()
+ {
+ if (this->futureInterface)
+ this->futureInterface->setFilterMode(true);
+ IterateKernelType::start();
+ }
+
+ bool runIteration(Iterator it, int index, T *)
+ {
+ if (keep(*it))
+ this->reportResult(&(*it), index);
+ else
+ this->reportResult(0, index);
+ return false;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *)
+ {
+ const int count = end - begin;
+ IntermediateResults<typename qValueType<Iterator>::value_type> results;
+ results.begin = begin;
+ results.end = end;
+ results.vector.reserve(count);
+
+ Iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ if (keep(*it))
+ results.vector.append(*it);
+ advance(it, 1);
+ }
+
+ this->reportResults(results.vector, begin, count);
+ return false;
+ }
+};
+
+template <typename Iterator, typename KeepFunctor>
+inline
+ThreadEngineStarter<typename qValueType<Iterator>::value_type>
+startFiltered(Iterator begin, Iterator end, KeepFunctor functor)
+{
+ return startThreadEngine(new FilteredEachKernel<Iterator, KeepFunctor>(begin, end, functor));
+}
+
+template <typename Sequence, typename KeepFunctor>
+inline ThreadEngineStarter<typename Sequence::value_type>
+startFiltered(const Sequence &sequence, KeepFunctor functor)
+{
+ typedef SequenceHolder1<Sequence,
+ FilteredEachKernel<typename Sequence::const_iterator, KeepFunctor>,
+ KeepFunctor>
+ SequenceHolderType;
+ return startThreadEngine(new SequenceHolderType(sequence, functor));
+}
+
+template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
+inline ThreadEngineStarter<ResultType> startFilteredReduced(const Sequence & sequence,
+ MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
+ ReduceOptions options)
+{
+ typedef typename Sequence::const_iterator Iterator;
+ typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type > Reducer;
+ typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
+ typedef SequenceHolder2<Sequence, FilteredReduceType, MapFunctor, ReduceFunctor> SequenceHolderType;
+ return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options));
+}
+
+
+template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
+inline ThreadEngineStarter<ResultType> startFilteredReduced(Iterator begin, Iterator end,
+ MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
+ ReduceOptions options)
+{
+ typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type> Reducer;
+ typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
+ return startThreadEngine(new FilteredReduceType(begin, end, mapFunctor, reduceFunctor, options));
+}
+
+
+} // namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentfunctionwrappers.h b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
new file mode 100644
index 0000000000..f31f7d2877
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_FUNCTIONWRAPPERS_H
+#define QTCONCURRENT_FUNCTIONWRAPPERS_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+template <typename T>
+class FunctionWrapper0
+{
+public:
+ typedef T (*FunctionPointerType)();
+ typedef T result_type;
+ inline FunctionWrapper0(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()()
+ {
+ return functionPointer();
+ }
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename U>
+class FunctionWrapper1
+{
+public:
+ typedef T (*FunctionPointerType)(U u);
+ typedef T result_type;
+ inline FunctionWrapper1(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()(U u)
+ {
+ return functionPointer(u);
+ }
+
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename U, typename V>
+class FunctionWrapper2
+{
+public:
+ typedef T (*FunctionPointerType)(U u, V v);
+ typedef T result_type;
+ inline FunctionWrapper2(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()(U u, V v)
+ {
+ return functionPointer(u, v);
+ }
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename C>
+class MemberFunctionWrapper
+{
+public:
+ typedef T (C::*FunctionPointerType)();
+ typedef T result_type;
+ inline MemberFunctionWrapper(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()(C &c)
+ {
+ return (c.*functionPointer)();
+ }
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename C, typename U>
+class MemberFunctionWrapper1
+{
+public:
+ typedef T (C::*FunctionPointerType)(U);
+ typedef T result_type;
+
+ inline MemberFunctionWrapper1(FunctionPointerType _functionPointer)
+ : functionPointer(_functionPointer)
+ { }
+
+ inline T operator()(C &c, U u)
+ {
+ return (c.*functionPointer)(u);
+ }
+
+private:
+ FunctionPointerType functionPointer;
+};
+
+template <typename T, typename C>
+class ConstMemberFunctionWrapper
+{
+public:
+ typedef T (C::*FunctionPointerType)() const;
+ typedef T result_type;
+ inline ConstMemberFunctionWrapper(FunctionPointerType _functionPointer)
+ :functionPointer(_functionPointer) { }
+
+ inline T operator()(const C &c) const
+ {
+ return (c.*functionPointer)();
+ }
+private:
+ FunctionPointerType functionPointer;
+};
+
+} // namespace QtConcurrent.
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.cpp b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp
new file mode 100644
index 0000000000..a59e6cfa47
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentiteratekernel.h"
+
+#if defined(Q_OS_MAC)
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <unistd.h>
+#elif defined(Q_OS_UNIX)
+#if defined(Q_OS_HURD)
+#include <sys/time.h>
+#endif
+#include <time.h>
+#include <unistd.h>
+#elif defined(Q_OS_WIN)
+#include <qt_windows.h>
+#endif
+
+#include "private/qfunctions_p.h"
+
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ TargetRatio = 100,
+ MedianSize = 7
+};
+
+#if defined(Q_OS_MAC)
+
+static qint64 getticks()
+{
+ return mach_absolute_time();
+}
+
+#elif defined(Q_OS_UNIX)
+
+
+static qint64 getticks()
+{
+#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
+ clockid_t clockId;
+
+#ifndef _POSIX_THREAD_CPUTIME
+ clockId = CLOCK_REALTIME;
+#elif (_POSIX_THREAD_CPUTIME-0 <= 0)
+ // if we don't have CLOCK_THREAD_CPUTIME_ID, we have to just use elapsed realtime instead
+ clockId = CLOCK_REALTIME;
+
+# if (_POSIX_THREAD_CPUTIME-0 == 0)
+ // detect availablility of CLOCK_THREAD_CPUTIME_ID
+ static long useThreadCpuTime = -2;
+ if (useThreadCpuTime == -2) {
+ // sysconf() will return either -1 or _POSIX_VERSION (don't care about thread races here)
+ useThreadCpuTime = sysconf(_SC_THREAD_CPUTIME);
+ }
+ if (useThreadCpuTime != -1)
+ clockId = CLOCK_THREAD_CPUTIME_ID;
+# endif
+#else
+ clockId = CLOCK_THREAD_CPUTIME_ID;
+#endif
+
+ struct timespec ts;
+ if (clock_gettime(clockId, &ts) == -1)
+ return 0;
+ return (ts.tv_sec * 1000000000) + ts.tv_nsec;
+#else
+
+#ifdef Q_OS_SYMBIAN
+ return clock();
+#else
+ // no clock_gettime(), fall back to wall time
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return (tv.tv_sec * 1000000) + tv.tv_usec;
+#endif
+
+#endif
+}
+
+#elif defined(Q_OS_WIN)
+
+static qint64 getticks()
+{
+ LARGE_INTEGER x;
+ if (!QueryPerformanceCounter(&x))
+ return 0;
+ return x.QuadPart;
+}
+
+#endif
+
+static double elapsed(qint64 after, qint64 before)
+{
+ return double(after - before);
+}
+
+namespace QtConcurrent {
+
+/*! \internal
+
+*/
+BlockSizeManager::BlockSizeManager(int iterationCount)
+: maxBlockSize(iterationCount / (QThreadPool::globalInstance()->maxThreadCount() * 2)),
+ beforeUser(0), afterUser(0),
+ controlPartElapsed(MedianSize), userPartElapsed(MedianSize),
+ m_blockSize(1)
+{ }
+
+// Records the time before user code.
+void BlockSizeManager::timeBeforeUser()
+{
+ if (blockSizeMaxed())
+ return;
+
+ beforeUser = getticks();
+ controlPartElapsed.addValue(elapsed(beforeUser, afterUser));
+}
+
+ // Records the time after user code and adjust the block size if we are spending
+ // to much time in the for control code compared with the user code.
+void BlockSizeManager::timeAfterUser()
+{
+ if (blockSizeMaxed())
+ return;
+
+ afterUser = getticks();
+ userPartElapsed.addValue(elapsed(afterUser, beforeUser));
+
+ if (controlPartElapsed.isMedianValid() == false)
+ return;
+
+ if (controlPartElapsed.median() * TargetRatio < userPartElapsed.median())
+ return;
+
+ m_blockSize = qMin(m_blockSize * 2, maxBlockSize);
+
+#ifdef QTCONCURRENT_FOR_DEBUG
+ qDebug() << QThread::currentThread() << "adjusting block size" << controlPartElapsed.median() << userPartElapsed.median() << m_blockSize;
+#endif
+
+ // Reset the medians after adjusting the block size so we get
+ // new measurements with the new block size.
+ controlPartElapsed.reset();
+ userPartElapsed.reset();
+}
+
+int BlockSizeManager::blockSize()
+{
+ return m_blockSize;
+}
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.h b/src/corelib/concurrent/qtconcurrentiteratekernel.h
new file mode 100644
index 0000000000..186f752e63
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentiteratekernel.h
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_ITERATEKERNEL_H
+#define QTCONCURRENT_ITERATEKERNEL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qtconcurrentmedian.h>
+#include <QtCore/qtconcurrentthreadengine.h>
+
+#ifndef QT_NO_STL
+# include <iterator>
+#endif
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+#ifndef QT_NO_STL
+ using std::advance;
+#else
+ template <typename It, typename T>
+ void advance(It &it, T value)
+ {
+ it+=value;
+ }
+#endif
+
+/*
+ The BlockSizeManager class manages how many iterations a thread should
+ reserve and process at a time. This is done by measuring the time spent
+ in the user code versus the control part code, and then increasing
+ the block size if the ratio between them is to small. The block size
+ management is done on the basis of the median of several timing measuremens,
+ and it is done induvidualy for each thread.
+*/
+class Q_CORE_EXPORT BlockSizeManager
+{
+public:
+ BlockSizeManager(int iterationCount);
+ void timeBeforeUser();
+ void timeAfterUser();
+ int blockSize();
+private:
+ inline bool blockSizeMaxed()
+ {
+ return (m_blockSize >= maxBlockSize);
+ }
+
+ const int maxBlockSize;
+ qint64 beforeUser;
+ qint64 afterUser;
+ Median<double> controlPartElapsed;
+ Median<double> userPartElapsed;
+ int m_blockSize;
+};
+
+template <typename T>
+class ResultReporter
+{
+public:
+ ResultReporter(ThreadEngine<T> *_threadEngine)
+ :threadEngine(_threadEngine)
+ {
+
+ }
+
+ void reserveSpace(int resultCount)
+ {
+ currentResultCount = resultCount;
+ vector.resize(qMax(resultCount, vector.count()));
+ }
+
+ void reportResults(int begin)
+ {
+ const int useVectorThreshold = 4; // Tunable parameter.
+ if (currentResultCount > useVectorThreshold) {
+ vector.resize(currentResultCount);
+ threadEngine->reportResults(vector, begin);
+ } else {
+ for (int i = 0; i < currentResultCount; ++i)
+ threadEngine->reportResult(&vector.at(i), begin + i);
+ }
+ }
+
+ inline T * getPointer()
+ {
+ return vector.data();
+ }
+
+ int currentResultCount;
+ ThreadEngine<T> *threadEngine;
+ QVector<T> vector;
+};
+
+template <>
+class ResultReporter<void>
+{
+public:
+ inline ResultReporter(ThreadEngine<void> *) { }
+ inline void reserveSpace(int) { };
+ inline void reportResults(int) { };
+ inline void * getPointer() { return 0; }
+};
+
+#ifndef QT_NO_STL
+inline bool selectIteration(std::bidirectional_iterator_tag)
+{
+ return false; // while
+}
+
+inline bool selectIteration(std::forward_iterator_tag)
+{
+ return false; // while
+}
+
+inline bool selectIteration(std::random_access_iterator_tag)
+{
+ return true; // for
+}
+#else
+// no stl support, always use while iteration
+template <typename T>
+inline bool selectIteration(T)
+{
+ return false; // while
+}
+#endif
+
+template <typename Iterator, typename T>
+class IterateKernel : public ThreadEngine<T>
+{
+public:
+ typedef T ResultType;
+
+ IterateKernel(Iterator _begin, Iterator _end)
+#if defined (QT_NO_STL)
+ : begin(_begin), end(_end), current(_begin), currentIndex(0),
+ forIteration(false), progressReportingEnabled(true)
+#else
+ : begin(_begin), end(_end), current(_begin), currentIndex(0),
+ forIteration(selectIteration(typename std::iterator_traits<Iterator>::iterator_category())), progressReportingEnabled(true)
+#endif
+ {
+#if defined (QT_NO_STL)
+ iterationCount = 0;
+#else
+ iterationCount = forIteration ? std::distance(_begin, _end) : 0;
+
+#endif
+ }
+
+ virtual ~IterateKernel() { }
+
+ virtual bool runIteration(Iterator it, int index , T *result)
+ { Q_UNUSED(it); Q_UNUSED(index); Q_UNUSED(result); return false; }
+ virtual bool runIterations(Iterator _begin, int beginIndex, int endIndex, T *results)
+ { Q_UNUSED(_begin); Q_UNUSED(beginIndex); Q_UNUSED(endIndex); Q_UNUSED(results); return false; }
+
+ void start()
+ {
+ progressReportingEnabled = this->isProgressReportingEnabled();
+ if (progressReportingEnabled && iterationCount > 0)
+ this->setProgressRange(0, iterationCount);
+ }
+
+ bool shouldStartThread()
+ {
+ if (forIteration)
+ return (currentIndex < iterationCount) && !this->shouldThrottleThread();
+ else // whileIteration
+ return (iteratorThreads == 0);
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ if (forIteration)
+ return this->forThreadFunction();
+ else // whileIteration
+ return this->whileThreadFunction();
+ }
+
+ ThreadFunctionResult forThreadFunction()
+ {
+ BlockSizeManager blockSizeManager(iterationCount);
+ ResultReporter<T> resultReporter(this);
+
+ for(;;) {
+ if (this->isCanceled())
+ break;
+
+ const int currentBlockSize = blockSizeManager.blockSize();
+
+ if (currentIndex >= iterationCount)
+ break;
+
+ // Atomically reserve a block of iterationCount for this thread.
+ const int beginIndex = currentIndex.fetchAndAddRelease(currentBlockSize);
+ const int endIndex = qMin(beginIndex + currentBlockSize, iterationCount);
+
+ if (beginIndex >= endIndex) {
+ // No more work
+ break;
+ }
+
+ this->waitForResume(); // (only waits if the qfuture is paused.)
+
+ if (shouldStartThread())
+ this->startThread();
+
+ const int finalBlockSize = endIndex - beginIndex; // block size adjusted for possible end-of-range
+ resultReporter.reserveSpace(finalBlockSize);
+
+ // Call user code with the current iteration range.
+ blockSizeManager.timeBeforeUser();
+ const bool resultsAvailable = this->runIterations(begin, beginIndex, endIndex, resultReporter.getPointer());
+ blockSizeManager.timeAfterUser();
+
+ if (resultsAvailable)
+ resultReporter.reportResults(beginIndex);
+
+ // Report progress if progress reporting enabled.
+ if (progressReportingEnabled) {
+ completed.fetchAndAddAcquire(finalBlockSize);
+ this->setProgressValue(this->completed);
+ }
+
+ if (this->shouldThrottleThread())
+ return ThrottleThread;
+ }
+ return ThreadFinished;
+ }
+
+ ThreadFunctionResult whileThreadFunction()
+ {
+ if (iteratorThreads.testAndSetAcquire(0, 1) == false)
+ return ThreadFinished;
+
+ ResultReporter<T> resultReporter(this);
+ resultReporter.reserveSpace(1);
+
+ while (current != end) {
+ // The following two lines breaks support for input iterators according to
+ // the sgi docs: dereferencing prev after calling ++current is not allowed
+ // on input iterators. (prev is dereferenced inside user.runIteration())
+ Iterator prev = current;
+ ++current;
+ int index = currentIndex.fetchAndAddRelaxed(1);
+ iteratorThreads.testAndSetRelease(1, 0);
+
+ this->waitForResume(); // (only waits if the qfuture is paused.)
+
+ if (shouldStartThread())
+ this->startThread();
+
+ const bool resultAavailable = this->runIteration(prev, index, resultReporter.getPointer());
+ if (resultAavailable)
+ resultReporter.reportResults(index);
+
+ if (this->shouldThrottleThread())
+ return ThrottleThread;
+
+ if (iteratorThreads.testAndSetAcquire(0, 1) == false)
+ return ThreadFinished;
+ }
+
+ return ThreadFinished;
+ }
+
+
+public:
+ const Iterator begin;
+ const Iterator end;
+ Iterator current;
+ QAtomicInt currentIndex;
+ bool forIteration;
+ QAtomicInt iteratorThreads;
+ int iterationCount;
+
+ bool progressReportingEnabled;
+ QAtomicInt completed;
+};
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentmap.cpp b/src/corelib/concurrent/qtconcurrentmap.cpp
new file mode 100644
index 0000000000..fe083f17a2
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmap.cpp
@@ -0,0 +1,402 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \namespace QtConcurrent
+ \inmodule QtCore
+ \since 4.4
+ \brief The QtConcurrent namespace provides high-level APIs that make it
+ possible to write multi-threaded programs without using low-level
+ threading primitives.
+
+ See the \l {Concurrent Programming}{Qt Concurrent} chapter in
+ the \l{threads.html}{threading} documentation.
+
+ \inheaderfile QtCore
+ \ingroup thread
+*/
+
+/*!
+ \namespace QtConcurrent::internal
+ \internal
+
+ \brief The QtConcurrent::internal namespace contains QtConcurrent
+ implementation details.
+*/
+
+/*!
+ \enum QtConcurrent::ReduceOption
+ This enum specifies the order of which results from the map or filter
+ function are passed to the reduce function.
+
+ \value UnorderedReduce Reduction is done in an arbitrary order.
+ \value OrderedReduce Reduction is done in the order of the
+ original sequence.
+ \value SequentialReduce Reduction is done sequentially: only one
+ thread will enter the reduce function at a time. (Parallel reduction
+ might be supported in a future version of Qt Concurrent.)
+*/
+
+/*!
+ \headerfile <QtConcurrentMap>
+ \title Concurrent Map and Map-Reduce
+ \ingroup thread
+
+ \brief The <QtConcurrentMap> header provides concurrent Map and MapReduce.
+
+ These functions are a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+
+ The QtConcurrent::map(), QtConcurrent::mapped() and
+ QtConcurrent::mappedReduced() functions run computations in parallel on
+ the items in a sequence such as a QList or a QVector. QtConcurrent::map()
+ modifies a sequence in-place, QtConcurrent::mapped() returns a new
+ sequence containing the modified content, and QtConcurrent::mappedReduced()
+ returns a single result.
+
+ Each of the above functions has a blocking variant that returns
+ the final result instead of a QFuture. You use them in the same
+ way as the asynchronous variants.
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 7
+
+ Note that the result types above are not QFuture objects, but real result
+ types (in this case, QList<QImage> and QImage).
+
+ \section1 Concurrent Map
+
+ QtConcurrent::mapped() takes an input sequence and a map function. This map
+ function is then called for each item in the sequence, and a new sequence
+ containing the return values from the map function is returned.
+
+ The map function must be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 0
+
+ T and U can be any type (and they can even be the same type), but T must
+ match the type stored in the sequence. The function returns the modified
+ or \e mapped content.
+
+ This example shows how to apply a scale function to all the items
+ in a sequence:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 1
+
+ The results of the map are made available through QFuture. See the
+ QFuture and QFutureWatcher documentation for more information on how to
+ use QFuture in your applications.
+
+ If you want to modify a sequence in-place, use QtConcurrent::map(). The
+ map function must then be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 2
+
+ Note that the return value and return type of the map function are not
+ used.
+
+ Using QtConcurrent::map() is similar to using QtConcurrent::mapped():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 3
+
+ Since the sequence is modified in place, QtConcurrent::map() does not
+ return any results via QFuture. However, you can still use QFuture and
+ QFutureWatcher to monitor the status of the map.
+
+ \section1 Concurrent Map-Reduce
+
+ QtConcurrent::mappedReduced() is similar to QtConcurrent::mapped(), but
+ instead of returning a sequence with the new results, the results are
+ combined into a single value using a reduce function.
+
+ The reduce function must be of the form:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 4
+
+ T is the type of the final result, U is the return type of the map
+ function. Note that the return value and return type of the reduce
+ function are not used.
+
+ Call QtConcurrent::mappedReduced() like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 5
+
+ The reduce function will be called once for each result returned by the map
+ function, and should merge the \e{intermediate} into the \e{result}
+ variable. QtConcurrent::mappedReduced() guarantees that only one thread
+ will call reduce at a time, so using a mutex to lock the result variable
+ is not necessary. The QtConcurrent::ReduceOptions enum provides a way to
+ control the order in which the reduction is done. If
+ QtConcurrent::UnorderedReduce is used (the default), the order is
+ undefined, while QtConcurrent::OrderedReduce ensures that the reduction
+ is done in the order of the original sequence.
+
+ \section1 Additional API Features
+
+ \section2 Using Iterators instead of Sequence
+
+ Each of the above functions has a variant that takes an iterator range
+ instead of a sequence. You use them in the same way as the sequence
+ variants:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 6
+
+ \section2 Blocking Variants
+
+ Each of the above functions has a blocking variant that returns
+ the final result instead of a QFuture. You use them in the same
+ way as the asynchronous variants.
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 7
+
+ Note that the result types above are not QFuture objects, but real result
+ types (in this case, QList<QImage> and QImage).
+
+ \section2 Using Member Functions
+
+ QtConcurrent::map(), QtConcurrent::mapped(), and
+ QtConcurrent::mappedReduced() accept pointers to member functions.
+ The member function class type must match the type stored in the sequence:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 8
+
+ Note that when using QtConcurrent::mappedReduced(), you can mix the use of
+ normal and member functions freely:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 9
+
+ \section2 Using Function Objects
+
+ QtConcurrent::map(), QtConcurrent::mapped(), and
+ QtConcurrent::mappedReduced() accept function objects, which can be used to
+ add state to a function call. The result_type typedef must define the
+ result type of the function call operator:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 14
+
+ \section2 Using Bound Function Arguments
+
+ Note that Qt does not provide support for bound functions. This is
+ provided by 3rd party libraries like
+ \l{http://www.boost.org/libs/bind/bind.html}{Boost} or
+ \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf}{C++
+ TR1 Library Extensions}.
+
+ If you want to use a map function that takes more than one argument you can
+ use boost::bind() or std::tr1::bind() to transform it onto a function that
+ takes one argument.
+
+ As an example, we'll use QImage::scaledToWidth():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 10
+
+ scaledToWidth takes three arguments (including the "this" pointer) and
+ can't be used with QtConcurrent::mapped() directly, because
+ QtConcurrent::mapped() expects a function that takes one argument. To use
+ QImage::scaledToWidth() with QtConcurrent::mapped() we have to provide a
+ value for the \e{width} and the \e{transformation mode}:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 11
+
+ The return value from boost::bind() is a function object (functor) with
+ the following signature:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 12
+
+ This matches what QtConcurrent::mapped() expects, and the complete example
+ becomes:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentmap.cpp 13
+*/
+
+/*!
+ \fn QFuture<void> QtConcurrent::map(Sequence &sequence, MapFunction function)
+ \relates <QtConcurrentMap>
+
+ Calls \a function once for each item in \a sequence. The \a function is
+ passed a reference to the item, so that any modifications done to the item
+ will appear in \a sequence.
+*/
+
+/*!
+ \fn QFuture<void> QtConcurrent::map(Iterator begin, Iterator end, MapFunction function)
+ \relates <QtConcurrentMap>
+
+ Calls \a function once for each item from \a begin to \a end. The
+ \a function is passed a reference to the item, so that any modifications
+ done to the item will appear in the sequence which the iterators belong to.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::mapped(const Sequence &sequence, MapFunction function)
+ \relates <QtConcurrentMap>
+
+ Calls \a function once for each item in \a sequence and returns a future
+ with each mapped item as a result. You can use QFuture::const_iterator or
+ QFutureIterator to iterate through the results.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::mapped(ConstIterator begin, ConstIterator end, MapFunction function)
+ \relates <QtConcurrentMap>
+
+ Calls \a function once for each item from \a begin to \a end and returns a
+ future with each mapped item as a result. You can use
+ QFuture::const_iterator or QFutureIterator to iterate through the results.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::mappedReduced(const Sequence &sequence,
+ MapFunction mapFunction, ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions)
+
+ \relates <QtConcurrentMap>
+
+ Calls \a mapFunction once for each item in \a sequence. The return value of
+ each \a mapFunction is passed to \a reduceFunction.
+
+ Note that while \a mapFunction is called concurrently, only one thread at a
+ time will call \a reduceFunction. The order in which \a reduceFunction is
+ called is determined by \a reduceOptions.
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::mappedReduced(ConstIterator begin,
+ ConstIterator end, MapFunction mapFunction, ReduceFunction reduceFunction,
+ QtConcurrent::ReduceOptions reduceOptions)
+
+ \relates <QtConcurrentMap>
+
+ Calls \a mapFunction once for each item from \a begin to \a end. The return
+ value of each \a mapFunction is passed to \a reduceFunction.
+
+ Note that while \a mapFunction is called concurrently, only one thread at a
+ time will call \a reduceFunction. By default, the order in which
+ \a reduceFunction is called is undefined.
+
+ \note QtConcurrent::OrderedReduce results in the ordered reduction.
+*/
+
+/*!
+ \fn void QtConcurrent::blockingMap(Sequence &sequence, MapFunction function)
+
+ Calls \a function once for each item in \a sequence. The \a function is
+ passed a reference to the item, so that any modifications done to the item
+ will appear in \a sequence.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa map()
+*/
+
+/*!
+ \fn void QtConcurrent::blockingMap(Iterator begin, Iterator end, MapFunction function)
+
+ Calls \a function once for each item from \a begin to \a end. The
+ \a function is passed a reference to the item, so that any modifications
+ done to the item will appear in the sequence which the iterators belong to.
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa map()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingMapped(const Sequence &sequence, MapFunction function)
+
+ Calls \a function once for each item in \a sequence and returns a Sequence containing
+ the results. The type of the results will match the type returned my the MapFunction.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa mapped()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingMapped(ConstIterator begin, ConstIterator end, MapFunction function)
+
+ Calls \a function once for each item from \a begin to \a end and returns a
+ container with the results. Specify the type of container as the a template
+ argument, like this:
+
+ \code
+ QList<int> ints = QtConcurrent::blockingMapped<QList<int> >(beginIterator, endIterator, fn);
+ \endcode
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa mapped()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingMappedReduced(const Sequence &sequence, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+
+ \relates <QtConcurrentMap>
+
+ Calls \a mapFunction once for each item in \a sequence. The return value of
+ each \a mapFunction is passed to \a reduceFunction.
+
+ Note that while \a mapFunction is called concurrently, only one thread at a
+ time will call \a reduceFunction. The order in which \a reduceFunction is
+ called is determined by \a reduceOptions.
+
+ \note This function will block until all items in the sequence have been processed.
+
+ \sa mapped()
+*/
+
+/*!
+ \fn T QtConcurrent::blockingMappedReduced(ConstIterator begin, ConstIterator end, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
+
+ \relates <QtConcurrentMap>
+
+ Calls \a mapFunction once for each item from \a begin to \a end. The return
+ value of each \a mapFunction is passed to \a reduceFunction.
+
+ Note that while \a mapFunction is called concurrently, only one thread at a
+ time will call \a reduceFunction. The order in which \a reduceFunction is
+ called is undefined.
+
+ \note This function will block until the iterator reaches the end of the
+ sequence being processed.
+
+ \sa blockingMappedReduced()
+*/
diff --git a/src/corelib/concurrent/qtconcurrentmap.h b/src/corelib/concurrent/qtconcurrentmap.h
new file mode 100644
index 0000000000..80edf7e136
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmap.h
@@ -0,0 +1,780 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_MAP_H
+#define QTCONCURRENT_MAP_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentmapkernel.h>
+#include <QtCore/qtconcurrentreducekernel.h>
+#include <QtCore/qtconcurrentfunctionwrappers.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifdef qdoc
+
+namespace QtConcurrent {
+
+ QFuture<void> map(Sequence &sequence, MapFunction function);
+ QFuture<void> map(Iterator begin, Iterator end, MapFunction function);
+
+ template <typename T>
+ QFuture<T> mapped(const Sequence &sequence, MapFunction function);
+ template <typename T>
+ QFuture<T> mapped(ConstIterator begin, ConstIterator end, MapFunction function);
+
+ template <typename T>
+ QFuture<T> mappedReduced(const Sequence &sequence,
+ MapFunction function,
+ ReduceFunction function,
+ QtConcurrent::ReduceOptions options = UnorderedReduce | SequentialReduce);
+ template <typename T>
+ QFuture<T> mappedReduced(ConstIterator begin,
+ ConstIterator end,
+ MapFunction function,
+ ReduceFunction function,
+ QtConcurrent::ReduceOptions options = UnorderedReduce | SequentialReduce);
+
+ void blockingMap(Sequence &sequence, MapFunction function);
+ void blockingMap(Iterator begin, Iterator end, MapFunction function);
+
+ template <typename T>
+ T blockingMapped(const Sequence &sequence, MapFunction function);
+ template <typename T>
+ T blockingMapped(ConstIterator begin, ConstIterator end, MapFunction function);
+
+ template <typename T>
+ T blockingMappedReduced(const Sequence &sequence,
+ MapFunction function,
+ ReduceFunction function,
+ QtConcurrent::ReduceOptions options = UnorderedReduce | SequentialReduce);
+ template <typename T>
+ T blockingMappedReduced(ConstIterator begin,
+ ConstIterator end,
+ MapFunction function,
+ ReduceFunction function,
+ QtConcurrent::ReduceOptions options = UnorderedReduce | SequentialReduce);
+
+} // namespace QtConcurrent
+
+#else
+
+namespace QtConcurrent {
+
+// map() on sequences
+template <typename Sequence, typename MapFunctor>
+QFuture<void> map(Sequence &sequence, MapFunctor map)
+{
+ return startMap(sequence.begin(), sequence.end(), map);
+}
+
+template <typename Sequence, typename T, typename U>
+QFuture<void> map(Sequence &sequence, T (map)(U))
+{
+ return startMap(sequence.begin(), sequence.end(), FunctionWrapper1<T, U>(map));
+}
+
+template <typename Sequence, typename T, typename C>
+QFuture<void> map(Sequence &sequence, T (C::*map)())
+{
+ return startMap(sequence.begin(), sequence.end(), MemberFunctionWrapper<T, C>(map));
+}
+
+// map() on iterators
+template <typename Iterator, typename MapFunctor>
+QFuture<void> map(Iterator begin, Iterator end, MapFunctor map)
+{
+ return startMap(begin, end, map);
+}
+
+template <typename Iterator, typename T, typename U>
+QFuture<void> map(Iterator begin, Iterator end, T (map)(U))
+{
+ return startMap(begin, end, FunctionWrapper1<T, U>(map));
+}
+
+template <typename Iterator, typename T, typename C>
+QFuture<void> map(Iterator begin, Iterator end, T (C::*map)())
+{
+ return startMap(begin, end, MemberFunctionWrapper<T, C>(map));
+}
+
+// mappedReduced() for sequences.
+template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, ResultType>
+ (sequence, map, reduce, options);
+}
+
+template <typename Sequence, typename MapFunctor, typename T, typename U, typename V>
+QFuture<U> mappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, U>
+ (sequence, map, FunctionWrapper2<T, U &, V>(reduce), options);
+}
+
+template <typename Sequence, typename MapFunctor, typename T, typename C, typename U>
+QFuture<C> mappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, C>
+ (sequence, map, MemberFunctionWrapper1<T, C, U>(reduce), options);
+}
+
+template <typename ResultType, typename Sequence, typename T, typename U, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(const Sequence &sequence,
+ T (map)(U),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, ResultType>
+ (sequence, FunctionWrapper1<T, U>(map), reduce, options);
+}
+
+template <typename ResultType, typename Sequence, typename T, typename C, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, ResultType>
+ (sequence, ConstMemberFunctionWrapper<T, C>(map), reduce, options);
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename W, typename X>
+QFuture<W> mappedReduced(const Sequence &sequence,
+ T (map)(U),
+ V (reduce)(W &, X),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, W>
+ (sequence, FunctionWrapper1<T, U>(map), FunctionWrapper2<V, W &, X>(reduce), options);
+}
+
+template <typename Sequence, typename T, typename C, typename U, typename V, typename W>
+QFuture<V> mappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, V> (sequence, ConstMemberFunctionWrapper<T, C>(map),
+ FunctionWrapper2<U, V &, W>(reduce), options);
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename C, typename W>
+QFuture<C> mappedReduced(const Sequence &sequence,
+ T (map)(U),
+ V (C::*reduce)(W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, C> (sequence, FunctionWrapper1<T, U>(map),
+ MemberFunctionWrapper1<V, C, W>(reduce), options);
+}
+
+template <typename Sequence, typename T, typename C, typename U,typename D, typename V>
+QFuture<D> mappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ U (D::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, D>(sequence, ConstMemberFunctionWrapper<T, C>(map),
+ MemberFunctionWrapper1<U, D, V>(reduce), options);
+}
+
+// mappedReduced() for iterators
+template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<ResultType, typename MapFunctor::result_type>
+ (begin, end, map, reduce, options);
+}
+
+template <typename Iterator, typename MapFunctor, typename T, typename U, typename V>
+QFuture<U> mappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ T (reduce)(U &, V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, U>
+ (begin, end, map, FunctionWrapper2<T, U &, V>(reduce), options);
+}
+
+template <typename Iterator, typename MapFunctor, typename T, typename C, typename U>
+QFuture<C> mappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ T (C::*reduce)(U),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<typename MapFunctor::result_type, C>
+ (begin, end, map, MemberFunctionWrapper1<T, C, U>(reduce), options);
+}
+
+template <typename ResultType, typename Iterator, typename T, typename U, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, ResultType>
+ (begin, end, FunctionWrapper1<T, U>(map), reduce, options);
+}
+
+template <typename ResultType, typename Iterator, typename T, typename C, typename ReduceFunctor>
+QFuture<ResultType> mappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, ResultType>
+ (begin, end, ConstMemberFunctionWrapper<T, C>(map), reduce, options);
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename W, typename X>
+QFuture<W> mappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ V (reduce)(W &, X),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, W>
+ (begin, end, FunctionWrapper1<T, U>(map), FunctionWrapper2<V, W &, X>(reduce), options);
+}
+
+template <typename Iterator, typename T, typename C, typename U, typename V, typename W>
+QFuture<V> mappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ U (reduce)(V &, W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, V>(begin, end, ConstMemberFunctionWrapper<T, C>(map),
+ FunctionWrapper2<U, V &, W>(reduce), options);
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename C, typename W>
+QFuture<C> mappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ V (C::*reduce)(W),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, C>
+ (begin, end, FunctionWrapper1<T, U>(map), MemberFunctionWrapper1<V, C, W>(reduce), options);
+}
+
+template <typename Iterator, typename T, typename C, typename U,typename D, typename V>
+QFuture<D> mappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ U (D::*reduce)(V),
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return startMappedReduced<T, D>(begin, end, ConstMemberFunctionWrapper<T, C>(map),
+ MemberFunctionWrapper1<U, D, V>(reduce), options);
+}
+
+// mapped() for sequences
+template <typename Sequence, typename MapFunctor>
+QFuture<typename MapFunctor::result_type> mapped(const Sequence &sequence, MapFunctor map)
+{
+ return startMapped<typename MapFunctor::result_type>(sequence, map);
+}
+
+template <typename Sequence, typename T, typename U>
+QFuture<T> mapped(const Sequence &sequence, T (map)(U))
+{
+ return startMapped<T>(sequence, FunctionWrapper1<T, U>(map));
+}
+
+template <typename Sequence, typename T, typename C>
+QFuture<T> mapped(const Sequence &sequence, T (C::*map)() const)
+{
+ return startMapped<T>(sequence, ConstMemberFunctionWrapper<T, C>(map));
+}
+
+// mapped() for iterator ranges.
+template <typename Iterator, typename MapFunctor>
+QFuture<typename MapFunctor::result_type> mapped(Iterator begin, Iterator end, MapFunctor map)
+{
+ return startMapped<Q_TYPENAME MapFunctor::result_type>(begin, end, map);
+}
+
+template <typename Iterator, typename T, typename U>
+QFuture<T> mapped(Iterator begin, Iterator end, T (map)(U))
+{
+ return startMapped<T>(begin, end, FunctionWrapper1<T, U>(map));
+}
+
+template <typename Iterator, typename T, typename C>
+QFuture<T> mapped(Iterator begin, Iterator end, T (C::*map)() const)
+{
+ return startMapped<T>(begin, end, ConstMemberFunctionWrapper<T, C>(map));
+}
+
+
+template <typename Sequence, typename MapFunctor>
+void blockingMap(Sequence &sequence, MapFunctor map)
+{
+ startMap(sequence.begin(), sequence.end(), map).startBlocking();
+}
+
+template <typename Sequence, typename T, typename U>
+void blockingMap(Sequence &sequence, T (map)(U))
+{
+ startMap(sequence.begin(), sequence.end(), QtConcurrent::FunctionWrapper1<T, U>(map)).startBlocking();
+}
+
+template <typename Sequence, typename T, typename C>
+void blockingMap(Sequence &sequence, T (C::*map)())
+{
+ startMap(sequence.begin(), sequence.end(), QtConcurrent::MemberFunctionWrapper<T, C>(map)).startBlocking();
+}
+
+template <typename Iterator, typename MapFunctor>
+void blockingMap(Iterator begin, Iterator end, MapFunctor map)
+{
+ startMap(begin, end, map).startBlocking();
+}
+
+template <typename Iterator, typename T, typename U>
+void blockingMap(Iterator begin, Iterator end, T (map)(U))
+{
+ startMap(begin, end, QtConcurrent::FunctionWrapper1<T, U>(map)).startBlocking();
+}
+
+template <typename Iterator, typename T, typename C>
+void blockingMap(Iterator begin, Iterator end, T (C::*map)())
+{
+ startMap(begin, end, QtConcurrent::MemberFunctionWrapper<T, C>(map)).startBlocking();
+}
+
+template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
+ResultType blockingMappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ ReduceFunctor reduce,
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, ResultType>
+ (sequence, map, reduce, options).startBlocking();
+}
+
+template <typename Sequence, typename MapFunctor, typename T, typename U, typename V>
+U blockingMappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ T (reduce)(U &, V),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, U>
+ (sequence,
+ map,
+ QtConcurrent::FunctionWrapper2<T, U &, V>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename MapFunctor, typename T, typename C, typename U>
+C blockingMappedReduced(const Sequence &sequence,
+ MapFunctor map,
+ T (C::*reduce)(U),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, C>
+ (sequence,
+ map,
+ QtConcurrent::MemberFunctionWrapper1<T, C, U>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Sequence, typename T, typename U, typename ReduceFunctor>
+ResultType blockingMappedReduced(const Sequence &sequence,
+ T (map)(U),
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, ResultType>
+ (sequence,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ reduce,
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Sequence, typename T, typename C, typename ReduceFunctor>
+ResultType blockingMappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, ResultType>
+ (sequence,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ reduce,
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename W, typename X>
+W blockingMappedReduced(const Sequence &sequence,
+ T (map)(U),
+ V (reduce)(W &, X),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, W>
+ (sequence,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ QtConcurrent::FunctionWrapper2<V, W &, X>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename T, typename C, typename U, typename V, typename W>
+V blockingMappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ U (reduce)(V &, W),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, V>
+ (sequence,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ QtConcurrent::FunctionWrapper2<U, V &, W>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename T, typename U, typename V, typename C, typename W>
+C blockingMappedReduced(const Sequence &sequence,
+ T (map)(U),
+ V (C::*reduce)(W),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, C>
+ (sequence,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ QtConcurrent::MemberFunctionWrapper1<V, C, W>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Sequence, typename T, typename C, typename U,typename D, typename V>
+D blockingMappedReduced(const Sequence &sequence,
+ T (C::*map)() const,
+ U (D::*reduce)(V),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, D>
+ (sequence,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ QtConcurrent::MemberFunctionWrapper1<U, D, V>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
+ResultType blockingMappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, ResultType>
+ (begin, end, map, reduce, options).startBlocking();
+}
+
+template <typename Iterator, typename MapFunctor, typename T, typename U, typename V>
+U blockingMappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ T (reduce)(U &, V),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, U>
+ (begin,
+ end,
+ map,
+ QtConcurrent::FunctionWrapper2<T, U &, V>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename MapFunctor, typename T, typename C, typename U>
+C blockingMappedReduced(Iterator begin,
+ Iterator end,
+ MapFunctor map,
+ T (C::*reduce)(U),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, C>
+ (begin,
+ end,
+ map,
+ QtConcurrent::MemberFunctionWrapper1<T, C, U>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Iterator, typename T, typename U, typename ReduceFunctor>
+ResultType blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, ResultType>
+ (begin,
+ end,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ reduce,
+ options)
+ .startBlocking();
+}
+
+template <typename ResultType, typename Iterator, typename T, typename C, typename ReduceFunctor>
+ResultType blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ ReduceFunctor reduce,
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, ResultType>
+ (begin,
+ end,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ reduce,
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename W, typename X>
+W blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ V (reduce)(W &, X),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, W>
+ (begin,
+ end,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ QtConcurrent::FunctionWrapper2<V, W &, X>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename T, typename C, typename U, typename V, typename W>
+V blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ U (reduce)(V &, W),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, V>
+ (begin,
+ end,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ QtConcurrent::FunctionWrapper2<U, V &, W>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename T, typename U, typename V, typename C, typename W>
+C blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (map)(U),
+ V (C::*reduce)(W),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, C>
+ (begin,
+ end,
+ QtConcurrent::FunctionWrapper1<T, U>(map),
+ QtConcurrent::MemberFunctionWrapper1<V, C, W>(reduce),
+ options)
+ .startBlocking();
+}
+
+template <typename Iterator, typename T, typename C, typename U,typename D, typename V>
+D blockingMappedReduced(Iterator begin,
+ Iterator end,
+ T (C::*map)() const,
+ U (D::*reduce)(V),
+ QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+{
+ return QtConcurrent::startMappedReduced<T, D>
+ (begin,
+ end,
+ QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
+ QtConcurrent::MemberFunctionWrapper1<U, D, V>(reduce),
+ options)
+ .startBlocking();
+}
+
+// mapped() for sequences with a different putput sequence type.
+template <typename OutputSequence, typename InputSequence, typename MapFunctor>
+OutputSequence blockingMapped(const InputSequence &sequence, MapFunctor map)
+{
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename OutputSequence, typename InputSequence, typename T, typename U>
+OutputSequence blockingMapped(const InputSequence &sequence, T (map)(U))
+{
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename OutputSequence, typename InputSequence, typename T, typename C>
+OutputSequence blockingMapped(const InputSequence &sequence, T (C::*map)() const)
+{
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
+
+// overloads for changing the container value type:
+template <template <typename> class Sequence, typename MapFunctor, typename T>
+Sequence<typename MapFunctor::result_type> blockingMapped(const Sequence<T> &sequence, MapFunctor map)
+{
+ typedef Sequence<typename MapFunctor::result_type> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <template <typename> class Sequence, typename T, typename U, typename V>
+Sequence<U> blockingMapped(const Sequence<T> &sequence, U (map)(V))
+{
+ typedef Sequence<U> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <template <typename> class Sequence, typename T, typename U, typename C>
+Sequence<U> blockingMapped(const Sequence<T> &sequence, U (C::*map)() const)
+{
+ typedef Sequence<U> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
+
+// overloads for changing the container value type from a QStringList:
+template <typename MapFunctor>
+QList<typename MapFunctor::result_type> blockingMapped(const QStringList &sequence, MapFunctor map)
+{
+ typedef QList<typename MapFunctor::result_type> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename U, typename V>
+QList<U> blockingMapped(const QStringList &sequence, U (map)(V))
+{
+ typedef QList<U> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename U, typename C>
+QList<U> blockingMapped(const QStringList &sequence, U (C::*map)() const)
+{
+ typedef QList<U> OutputSequence;
+ return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+// mapped() for iterator ranges
+template <typename Sequence, typename Iterator, typename MapFunctor>
+Sequence blockingMapped(Iterator begin, Iterator end, MapFunctor map)
+{
+ return blockingMappedReduced(begin, end, map, &Sequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename Sequence, typename Iterator, typename T, typename U>
+Sequence blockingMapped(Iterator begin, Iterator end, T (map)(U))
+{
+ return blockingMappedReduced(begin, end, map, &Sequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+template <typename Sequence, typename Iterator, typename T, typename C>
+Sequence blockingMapped(Iterator begin, Iterator end, T (C::*map)() const)
+{
+ return blockingMappedReduced(begin, end, map, &Sequence::push_back,
+ QtConcurrent::OrderedReduce);
+}
+
+} // namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentmapkernel.h b/src/corelib/concurrent/qtconcurrentmapkernel.h
new file mode 100644
index 0000000000..20b9944b16
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmapkernel.h
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_MAPKERNEL_H
+#define QTCONCURRENT_MAPKERNEL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentiteratekernel.h>
+#include <QtCore/qtconcurrentreducekernel.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+namespace QtConcurrent {
+
+// map kernel, works with both parallel-for and parallel-while
+template <typename Iterator, typename MapFunctor>
+class MapKernel : public IterateKernel<Iterator, void>
+{
+ MapFunctor map;
+public:
+ typedef void ReturnType;
+ MapKernel(Iterator begin, Iterator end, MapFunctor _map)
+ : IterateKernel<Iterator, void>(begin, end), map(_map)
+ { }
+
+ bool runIteration(Iterator it, int, void *)
+ {
+ map(*it);
+ return false;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, void *)
+ {
+ Iterator it = sequenceBeginIterator;
+ advance(it, beginIndex);
+ for (int i = beginIndex; i < endIndex; ++i) {
+ runIteration(it, i, 0);
+ advance(it, 1);
+ }
+
+ return false;
+ }
+};
+
+template <typename ReducedResultType,
+ typename Iterator,
+ typename MapFunctor,
+ typename ReduceFunctor,
+ typename Reducer = ReduceKernel<ReduceFunctor,
+ ReducedResultType,
+ typename MapFunctor::result_type> >
+class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType>
+{
+ ReducedResultType reducedResult;
+ MapFunctor map;
+ ReduceFunctor reduce;
+ Reducer reducer;
+public:
+ typedef ReducedResultType ReturnType;
+ MappedReducedKernel(Iterator begin, Iterator end, MapFunctor _map, ReduceFunctor _reduce, ReduceOptions reduceOptions)
+ : IterateKernel<Iterator, ReducedResultType>(begin, end), reducedResult(), map(_map), reduce(_reduce), reducer(reduceOptions)
+ { }
+
+ MappedReducedKernel(ReducedResultType initialValue,
+ MapFunctor _map,
+ ReduceFunctor _reduce)
+ : reducedResult(initialValue), map(_map), reduce(_reduce)
+ { }
+
+ bool runIteration(Iterator it, int index, ReducedResultType *)
+ {
+ IntermediateResults<typename MapFunctor::result_type> results;
+ results.begin = index;
+ results.end = index + 1;
+
+ results.vector.append(map(*it));
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *)
+ {
+ IntermediateResults<typename MapFunctor::result_type> results;
+ results.begin = begin;
+ results.end = end;
+ results.vector.reserve(end - begin);
+
+ Iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ results.vector.append(map(*(it)));
+ advance(it, 1);
+ }
+
+ reducer.runReduce(reduce, reducedResult, results);
+ return false;
+ }
+
+ void finish()
+ {
+ reducer.finish(reduce, reducedResult);
+ }
+
+ bool shouldThrottleThread()
+ {
+ return IterateKernel<Iterator, ReducedResultType>::shouldThrottleThread() || reducer.shouldThrottle();
+ }
+
+ bool shouldStartThread()
+ {
+ return IterateKernel<Iterator, ReducedResultType>::shouldStartThread() && reducer.shouldStartThread();
+ }
+
+ typedef ReducedResultType ResultType;
+ ReducedResultType *result()
+ {
+ return &reducedResult;
+ }
+};
+
+template <typename Iterator, typename MapFunctor>
+class MappedEachKernel : public IterateKernel<Iterator, typename MapFunctor::result_type>
+{
+ MapFunctor map;
+ typedef typename MapFunctor::result_type T;
+public:
+ typedef T ReturnType;
+ typedef T ResultType;
+
+ MappedEachKernel(Iterator begin, Iterator end, MapFunctor _map)
+ : IterateKernel<Iterator, T>(begin, end), map(_map) { }
+
+ bool runIteration(Iterator it, int, T *result)
+ {
+ *result = map(*it);
+ return true;
+ }
+
+ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *results)
+ {
+
+ Iterator it = sequenceBeginIterator;
+ advance(it, begin);
+ for (int i = begin; i < end; ++i) {
+ runIteration(it, i, results + (i - begin));
+ advance(it, 1);
+ }
+
+ return true;
+ }
+};
+
+template <typename Iterator, typename Functor>
+inline ThreadEngineStarter<void> startMap(Iterator begin, Iterator end, Functor functor)
+{
+ return startThreadEngine(new MapKernel<Iterator, Functor>(begin, end, functor));
+}
+
+template <typename T, typename Iterator, typename Functor>
+inline ThreadEngineStarter<T> startMapped(Iterator begin, Iterator end, Functor functor)
+{
+ return startThreadEngine(new MappedEachKernel<Iterator, Functor>(begin, end, functor));
+}
+
+/*
+ The SequnceHolder class is used to hold a reference to the
+ sequence we are working on.
+*/
+template <typename Sequence, typename Base, typename Functor>
+struct SequenceHolder1 : public Base
+{
+ SequenceHolder1(const Sequence &_sequence, Functor functor)
+ : Base(_sequence.begin(), _sequence.end(), functor), sequence(_sequence)
+ { }
+
+ Sequence sequence;
+
+ void finish()
+ {
+ Base::finish();
+ // Clear the sequence to make sure all temporaries are destroyed
+ // before finished is signaled.
+ sequence = Sequence();
+ }
+};
+
+template <typename T, typename Sequence, typename Functor>
+inline ThreadEngineStarter<T> startMapped(const Sequence &sequence, Functor functor)
+{
+ typedef SequenceHolder1<Sequence,
+ MappedEachKernel<typename Sequence::const_iterator , Functor>, Functor>
+ SequenceHolderType;
+
+ return startThreadEngine(new SequenceHolderType(sequence, functor));
+}
+
+template <typename IntermediateType, typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
+inline ThreadEngineStarter<ResultType> startMappedReduced(const Sequence & sequence,
+ MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
+ ReduceOptions options)
+{
+ typedef typename Sequence::const_iterator Iterator;
+ typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
+ typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> MappedReduceType;
+ typedef SequenceHolder2<Sequence, MappedReduceType, MapFunctor, ReduceFunctor> SequenceHolderType;
+ return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options));
+}
+
+template <typename IntermediateType, typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
+inline ThreadEngineStarter<ResultType> startMappedReduced(Iterator begin, Iterator end,
+ MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
+ ReduceOptions options)
+{
+ typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
+ typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> MappedReduceType;
+ return startThreadEngine(new MappedReduceType(begin, end, mapFunctor, reduceFunctor, options));
+}
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentmedian.h b/src/corelib/concurrent/qtconcurrentmedian.h
new file mode 100644
index 0000000000..42b338b146
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmedian.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_MEDIAN_H
+#define QTCONCURRENT_MEDIAN_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qvector.h>
+#include <QtCore/qalgorithms.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+template <typename T>
+class Median
+{
+public:
+ Median(int _bufferSize)
+ : currentMedian(), bufferSize(_bufferSize), currentIndex(0), valid(false), dirty(true)
+ {
+ values.resize(bufferSize);
+ }
+
+ void reset()
+ {
+ values.fill(0);
+ currentIndex = 0;
+ valid = false;
+ dirty = true;
+ }
+
+ void addValue(T value)
+ {
+ currentIndex = ((currentIndex + 1) % bufferSize);
+ if (valid == false && currentIndex % bufferSize == 0)
+ valid = true;
+
+ // Only update the cached median value when we have to, that
+ // is when the new value is on then other side of the median
+ // compared to the current value at the index.
+ const T currentIndexValue = values[currentIndex];
+ if ((currentIndexValue > currentMedian && currentMedian > value)
+ || (currentMedian > currentIndexValue && value > currentMedian)) {
+ dirty = true;
+ }
+
+ values[currentIndex] = value;
+ }
+
+ bool isMedianValid() const
+ {
+ return valid;
+ }
+
+ T median()
+ {
+ if (dirty) {
+ dirty = false;
+ QVector<T> sorted = values;
+ qSort(sorted);
+ currentMedian = sorted.at(bufferSize / 2 + 1);
+ }
+ return currentMedian;
+ }
+private:
+ QVector<T> values;
+ T currentMedian;
+ int bufferSize;
+ int currentIndex;
+ bool valid;
+ bool dirty;
+};
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentreducekernel.h b/src/corelib/concurrent/qtconcurrentreducekernel.h
new file mode 100644
index 0000000000..d8651ab4cc
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentreducekernel.h
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_REDUCEKERNEL_H
+#define QTCONCURRENT_REDUCEKERNEL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qthreadpool.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+namespace QtConcurrent {
+
+#ifndef qdoc
+
+/*
+ The ReduceQueueStartLimit and ReduceQueueThrottleLimit constants
+ limit the reduce queue size for MapReduce. When the number of
+ reduce blocks in the queue exceeds ReduceQueueStartLimit,
+ MapReduce won't start any new threads, and when it exceeds
+ ReduceQueueThrottleLimit running threads will be stopped.
+*/
+enum {
+ ReduceQueueStartLimit = 20,
+ ReduceQueueThrottleLimit = 30
+};
+
+// IntermediateResults holds a block of intermediate results from a
+// map or filter functor. The begin/end offsets indicates the origin
+// and range of the block.
+template <typename T>
+class IntermediateResults
+{
+public:
+ int begin, end;
+ QVector<T> vector;
+};
+
+#endif // qdoc
+
+enum ReduceOption {
+ UnorderedReduce = 0x1,
+ OrderedReduce = 0x2,
+ SequentialReduce = 0x4
+ // ParallelReduce = 0x8
+};
+Q_DECLARE_FLAGS(ReduceOptions, ReduceOption)
+Q_DECLARE_OPERATORS_FOR_FLAGS(ReduceOptions)
+
+#ifndef qdoc
+
+// supports both ordered and out-of-order reduction
+template <typename ReduceFunctor, typename ReduceResultType, typename T>
+class ReduceKernel
+{
+ typedef QMap<int, IntermediateResults<T> > ResultsMap;
+
+ const ReduceOptions reduceOptions;
+
+ QMutex mutex;
+ int progress, resultsMapSize, threadCount;
+ ResultsMap resultsMap;
+
+ bool canReduce(int begin) const
+ {
+ return (((reduceOptions & UnorderedReduce)
+ && progress == 0)
+ || ((reduceOptions & OrderedReduce)
+ && progress == begin));
+ }
+
+ void reduceResult(ReduceFunctor &reduce,
+ ReduceResultType &r,
+ const IntermediateResults<T> &result)
+ {
+ for (int i = 0; i < result.vector.size(); ++i) {
+ reduce(r, result.vector.at(i));
+ }
+ }
+
+ void reduceResults(ReduceFunctor &reduce,
+ ReduceResultType &r,
+ ResultsMap &map)
+ {
+ typename ResultsMap::iterator it = map.begin();
+ while (it != map.end()) {
+ reduceResult(reduce, r, it.value());
+ ++it;
+ }
+ }
+
+public:
+ ReduceKernel(ReduceOptions _reduceOptions)
+ : reduceOptions(_reduceOptions), progress(0), resultsMapSize(0),
+ threadCount(QThreadPool::globalInstance()->maxThreadCount())
+ { }
+
+ void runReduce(ReduceFunctor &reduce,
+ ReduceResultType &r,
+ const IntermediateResults<T> &result)
+ {
+ QMutexLocker locker(&mutex);
+ if (!canReduce(result.begin)) {
+ ++resultsMapSize;
+ resultsMap.insert(result.begin, result);
+ return;
+ }
+
+ if (reduceOptions & UnorderedReduce) {
+ // UnorderedReduce
+ progress = -1;
+
+ // reduce this result
+ locker.unlock();
+ reduceResult(reduce, r, result);
+ locker.relock();
+
+ // reduce all stored results as well
+ while (!resultsMap.isEmpty()) {
+ ResultsMap resultsMapCopy = resultsMap;
+ resultsMap.clear();
+
+ locker.unlock();
+ reduceResults(reduce, r, resultsMapCopy);
+ locker.relock();
+
+ resultsMapSize -= resultsMapCopy.size();
+ }
+
+ progress = 0;
+ } else {
+ // reduce this result
+ locker.unlock();
+ reduceResult(reduce, r, result);
+ locker.relock();
+
+ // OrderedReduce
+ progress += result.end - result.begin;
+
+ // reduce as many other results as possible
+ typename ResultsMap::iterator it = resultsMap.begin();
+ while (it != resultsMap.end()) {
+ if (it.value().begin != progress)
+ break;
+
+ locker.unlock();
+ reduceResult(reduce, r, it.value());
+ locker.relock();
+
+ --resultsMapSize;
+ progress += it.value().end - it.value().begin;
+ it = resultsMap.erase(it);
+ }
+ }
+ }
+
+ // final reduction
+ void finish(ReduceFunctor &reduce, ReduceResultType &r)
+ {
+ reduceResults(reduce, r, resultsMap);
+ }
+
+ inline bool shouldThrottle()
+ {
+ return (resultsMapSize > (ReduceQueueThrottleLimit * threadCount));
+ }
+
+ inline bool shouldStartThread()
+ {
+ return (resultsMapSize <= (ReduceQueueStartLimit * threadCount));
+ }
+};
+
+template <typename Sequence, typename Base, typename Functor1, typename Functor2>
+struct SequenceHolder2 : public Base
+{
+ SequenceHolder2(const Sequence &_sequence,
+ Functor1 functor1,
+ Functor2 functor2,
+ ReduceOptions reduceOptions)
+ : Base(_sequence.begin(), _sequence.end(), functor1, functor2, reduceOptions),
+ sequence(_sequence)
+ { }
+
+ Sequence sequence;
+
+ void finish()
+ {
+ Base::finish();
+ // Clear the sequence to make sure all temporaries are destroyed
+ // before finished is signaled.
+ sequence = Sequence();
+ }
+};
+
+#endif //qdoc
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentresultstore.cpp b/src/corelib/concurrent/qtconcurrentresultstore.cpp
new file mode 100644
index 0000000000..16714caa74
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentresultstore.cpp
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentresultstore.h"
+
+#ifndef QT_NO_QFUTURE
+
+QT_BEGIN_NAMESPACE
+
+namespace QtConcurrent {
+
+ResultIteratorBase::ResultIteratorBase()
+ : mapIterator(QMap<int, ResultItem>::const_iterator()), m_vectorIndex(0) { }
+ResultIteratorBase::ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex)
+ : mapIterator(_mapIterator), m_vectorIndex(_vectorIndex) { }
+
+int ResultIteratorBase::vectorIndex() const { return m_vectorIndex; }
+int ResultIteratorBase::resultIndex() const { return mapIterator.key() + m_vectorIndex; }
+
+ResultIteratorBase ResultIteratorBase::operator++()
+{
+ if (canIncrementVectorIndex()) {
+ ++m_vectorIndex;
+ } else {
+ ++mapIterator;
+ m_vectorIndex = 0;
+ }
+ return *this;
+}
+
+int ResultIteratorBase::batchSize() const
+{
+ return mapIterator.value().count();
+}
+
+void ResultIteratorBase::batchedAdvance()
+{
+ ++mapIterator;
+ m_vectorIndex = 0;
+}
+
+bool ResultIteratorBase::operator==(const ResultIteratorBase &other) const
+{
+ return (mapIterator == other.mapIterator && m_vectorIndex == other.m_vectorIndex);
+}
+
+bool ResultIteratorBase::operator!=(const ResultIteratorBase &other) const
+{
+ return !operator==(other);
+}
+
+bool ResultIteratorBase::isVector() const
+{
+ return mapIterator.value().isVector();
+}
+
+bool ResultIteratorBase::canIncrementVectorIndex() const
+{
+ return (m_vectorIndex + 1 < mapIterator.value().m_count);
+}
+
+ResultStoreBase::ResultStoreBase()
+ : insertIndex(0), resultCount(0), m_filterMode(false), filteredResults(0) { }
+
+void ResultStoreBase::setFilterMode(bool enable)
+{
+ m_filterMode = enable;
+}
+
+bool ResultStoreBase::filterMode() const
+{
+ return m_filterMode;
+}
+
+void ResultStoreBase::syncResultCount()
+{
+ ResultIteratorBase it = resultAt(resultCount);
+ while (it != end()) {
+ resultCount += it.batchSize();
+ it = resultAt(resultCount);
+ }
+}
+
+void ResultStoreBase::insertResultItemIfValid(int index, ResultItem &resultItem)
+{
+ if (resultItem.isValid()) {
+ m_results[index] = resultItem;
+ syncResultCount();
+ } else {
+ filteredResults += resultItem.count();
+ }
+}
+
+int ResultStoreBase::insertResultItem(int index, ResultItem &resultItem)
+{
+ int storeIndex;
+ if (m_filterMode && index != -1 && index > insertIndex) {
+ pendingResults[index] = resultItem;
+ storeIndex = index;
+ } else {
+ storeIndex = updateInsertIndex(index, resultItem.count());
+ insertResultItemIfValid(storeIndex - filteredResults, resultItem);
+ }
+ syncPendingResults();
+ return storeIndex;
+}
+
+void ResultStoreBase::syncPendingResults()
+{
+ // check if we can insert any of the pending results:
+ QMap<int, ResultItem>::iterator it = pendingResults.begin();
+ while (it != pendingResults.end()) {
+ int index = it.key();
+ if (index != resultCount + filteredResults)
+ break;
+
+ ResultItem result = it.value();
+ insertResultItemIfValid(index - filteredResults, result);
+ pendingResults.erase(it);
+ it = pendingResults.begin();
+ }
+}
+
+int ResultStoreBase::addResult(int index, const void *result)
+{
+ ResultItem resultItem(result, 0); // 0 means "not a vector"
+ return insertResultItem(index, resultItem);
+}
+
+int ResultStoreBase::addResults(int index, const void *results, int vectorSize, int totalCount)
+{
+ if (m_filterMode == false || vectorSize == totalCount) {
+ ResultItem resultItem(results, vectorSize);
+ return insertResultItem(index, resultItem);
+ } else {
+ if (vectorSize > 0) {
+ ResultItem filteredIn(results, vectorSize);
+ insertResultItem(index, filteredIn);
+ }
+ ResultItem filteredAway(0, totalCount - vectorSize);
+ return insertResultItem(index + vectorSize, filteredAway);
+ }
+}
+
+ResultIteratorBase ResultStoreBase::begin() const
+{
+ return ResultIteratorBase(m_results.begin());
+}
+
+ResultIteratorBase ResultStoreBase::end() const
+{
+ return ResultIteratorBase(m_results.end());
+}
+
+bool ResultStoreBase::hasNextResult() const
+{
+ return begin() != end();
+}
+
+ResultIteratorBase ResultStoreBase::resultAt(int index) const
+{
+ if (m_results.isEmpty())
+ return ResultIteratorBase(m_results.end());
+ QMap<int, ResultItem>::const_iterator it = m_results.lowerBound(index);
+
+ // lowerBound returns either an iterator to the result or an iterator
+ // to the nearest greater index. If the latter happens it might be
+ // that the result is stored in a vector at the previous index.
+ if (it == m_results.end()) {
+ --it;
+ if (it.value().isVector() == false) {
+ return ResultIteratorBase(m_results.end());
+ }
+ } else {
+ if (it.key() > index) {
+ if (it == m_results.begin())
+ return ResultIteratorBase(m_results.end());
+ --it;
+ }
+ }
+
+ const int vectorIndex = index - it.key();
+
+ if (vectorIndex >= it.value().count())
+ return ResultIteratorBase(m_results.end());
+ else if (it.value().isVector() == false && vectorIndex != 0)
+ return ResultIteratorBase(m_results.end());
+ return ResultIteratorBase(it, vectorIndex);
+}
+
+bool ResultStoreBase::contains(int index) const
+{
+ return (resultAt(index) != end());
+}
+
+int ResultStoreBase::count() const
+{
+ return resultCount;
+}
+
+// returns the insert index, calling this function with
+// index equal to -1 returns the next available index.
+int ResultStoreBase::updateInsertIndex(int index, int _count)
+{
+ if (index == -1) {
+ index = insertIndex;
+ insertIndex += _count;
+ } else {
+ insertIndex = qMax(index + _count, insertIndex);
+ }
+ return index;
+}
+
+} // namespace QtConcurrent
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qtconcurrentresultstore.h b/src/corelib/concurrent/qtconcurrentresultstore.h
new file mode 100644
index 0000000000..428de717c9
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentresultstore.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_RESULTSTORE_H
+#define QTCONCURRENT_RESULTSTORE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_QFUTURE
+
+#include <QtCore/qmap.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+/*
+ ResultStore stores indexed results. Results can be added and retrieved
+ either individually batched in a QVector. Retriveing results and checking
+ which indexes are in the store can be done either by iterating or by random
+ accees. In addition results kan be removed from the front of the store,
+ either individually or in batches.
+*/
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+class ResultItem
+{
+public:
+ ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results
+ ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
+ ResultItem() : m_count(0), result(0) { }
+ bool isValid() const { return result != 0; }
+ bool isVector() const { return m_count != 0; }
+ int count() const { return (m_count == 0) ? 1 : m_count; }
+ int m_count; // result is either a pointer to a result or to a vector of results,
+ const void *result; // if count is 0 it's a result, otherwise it's a vector.
+};
+
+class Q_CORE_EXPORT ResultIteratorBase
+{
+public:
+ ResultIteratorBase();
+ ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex = 0);
+ int vectorIndex() const;
+ int resultIndex() const;
+
+ ResultIteratorBase operator++();
+ int batchSize() const;
+ void batchedAdvance();
+ bool operator==(const ResultIteratorBase &other) const;
+ bool operator!=(const ResultIteratorBase &other) const;
+ bool isVector() const;
+ bool canIncrementVectorIndex() const;
+protected:
+ QMap<int, ResultItem>::const_iterator mapIterator;
+ int m_vectorIndex;
+};
+
+template <typename T>
+class ResultIterator : public ResultIteratorBase
+{
+public:
+ ResultIterator(const ResultIteratorBase &base)
+ : ResultIteratorBase(base) { }
+
+ const T &value() const
+ {
+ return *pointer();
+ }
+
+ const T *pointer() const
+ {
+ if (mapIterator.value().isVector())
+ return &(reinterpret_cast<const QVector<T> *>(mapIterator.value().result)->at(m_vectorIndex));
+ else
+ return reinterpret_cast<const T *>(mapIterator.value().result);
+ }
+};
+
+class Q_CORE_EXPORT ResultStoreBase
+{
+public:
+ ResultStoreBase();
+ void setFilterMode(bool enable);
+ bool filterMode() const;
+ int addResult(int index, const void *result);
+ int addResults(int index, const void *results, int vectorSize, int logicalCount);
+ ResultIteratorBase begin() const;
+ ResultIteratorBase end() const;
+ bool hasNextResult() const;
+ ResultIteratorBase resultAt(int index) const;
+ bool contains(int index) const;
+ int count() const;
+ virtual ~ResultStoreBase() { };
+
+protected:
+ int insertResultItem(int index, ResultItem &resultItem);
+ void insertResultItemIfValid(int index, ResultItem &resultItem);
+ void syncPendingResults();
+ void syncResultCount();
+ int updateInsertIndex(int index, int _count);
+
+ QMap<int, ResultItem> m_results;
+ int insertIndex; // The index where the next results(s) will be inserted.
+ int resultCount; // The number of consecutive results stored, starting at index 0.
+
+ bool m_filterMode;
+ QMap<int, ResultItem> pendingResults;
+ int filteredResults;
+
+};
+
+template <typename T>
+class ResultStore : public ResultStoreBase
+{
+public:
+ ResultStore() { }
+
+ ResultStore(const ResultStoreBase &base)
+ : ResultStoreBase(base) { }
+
+ int addResult(int index, const T *result)
+ {
+ if (result == 0)
+ return ResultStoreBase::addResult(index, result);
+ else
+ return ResultStoreBase::addResult(index, new T(*result));
+ }
+
+ int addResults(int index, const QVector<T> *results)
+ {
+ return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), results->count());
+ }
+
+ int addResults(int index, const QVector<T> *results, int totalCount)
+ {
+ return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), totalCount);
+ }
+
+ int addCanceledResult(int index)
+ {
+ return addResult(index, 0);
+ }
+
+ int addCanceledResults(int index, int _count)
+ {
+ QVector<T> empty;
+ return addResults(index, &empty, _count);
+ }
+
+ ResultIterator<T> begin() const
+ {
+ return static_cast<ResultIterator<T> >(ResultStoreBase::begin());
+ }
+
+ ResultIterator<T> end() const
+ {
+ return static_cast<ResultIterator<T> >(ResultStoreBase::end());
+ }
+
+ ResultIterator<T> resultAt(int index) const
+ {
+ return static_cast<ResultIterator<T> >(ResultStoreBase::resultAt(index));
+ }
+
+ void clear()
+ {
+ QMap<int, ResultItem>::const_iterator mapIterator = m_results.constBegin();
+ while (mapIterator != m_results.constEnd()) {
+ if (mapIterator.value().isVector())
+ delete reinterpret_cast<const QVector<T> *>(mapIterator.value().result);
+ else
+ delete reinterpret_cast<const T *>(mapIterator.value().result);
+ ++mapIterator;
+ }
+ resultCount = 0;
+ m_results.clear();
+ }
+
+ ~ResultStore()
+ {
+ clear();
+ }
+
+};
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentrun.cpp b/src/corelib/concurrent/qtconcurrentrun.cpp
new file mode 100644
index 0000000000..4c685dd23b
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrun.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtConcurrentRun>
+ \title Asynchronous Run
+
+ \brief The <QtConcurrentRun> header provides a way to run a function in a
+ separate thread.
+
+ \ingroup thread
+
+ This function is a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+
+ The QtConcurrent::run() function runs a function in a separate thread.
+ The return value of the function is made available through the QFuture API.
+
+ \section1 Running a Function in a Separate Thread
+
+ To run a function in another thread, use QtConcurrent::run():
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 0
+
+ This will run \e aFunction in a separate thread obtained from the default
+ QThreadPool. You can use the QFuture and QFutureWatcher classes to monitor
+ the status of the function.
+
+ \section1 Passing Arguments to the Function
+
+ Passing arguments to the function is done by adding them to the
+ QtConcurrent::run() call immediately after the function name. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 1
+
+ A copy of each argument is made at the point where QtConcurrent::run() is
+ called, and these values are passed to the thread when it begins executing
+ the function. Changes made to the arguments after calling
+ QtConcurrent::run() are \e not visible to the thread.
+
+ \section1 Returning Values from the Function
+
+ Any return value from the function is available via QFuture:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 2
+
+ As documented above, passing arguments is done like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 3
+
+ Note that the QFuture::result() function blocks and waits for the result
+ to become available. Use QFutureWatcher to get notification when the
+ function has finished execution and the result is available.
+
+ \section1 Additional API Features
+
+ \section2 Using Member Functions
+
+ QtConcurrent::run() also accepts pointers to member functions. The first
+ argument must be either a const reference or a pointer to an instance of
+ the class. Passing by const reference is useful when calling const member
+ functions; passing by pointer is useful for calling non-const member
+ functions that modify the instance.
+
+ For example, calling QByteArray::split() (a const member function) in a
+ separate thread is done like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 4
+
+ Calling a non-const member function is done like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 5
+
+ \section2 Using Bound Function Arguments
+
+ Note that Qt does not provide support for bound functions. This is
+ provided by 3rd party libraries like
+ \l{http://www.boost.org/libs/bind/bind.html}{Boost} or
+ \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf}
+ {C++ TR1 Library Extensions}.
+
+ You can use boost::bind() or std::tr1::bind() to \e bind a number of
+ arguments to a function when called. There are number of reasons for doing
+ this:
+
+ \list
+ \o To call a function that takes more than 5 arguments.
+ \o To simplify calling a function with constant arguments.
+ \o Changing the order of arguments.
+ \endlist
+
+ See the documentation for the relevant functions for details on how to use
+ the bind API.
+
+ Calling a bound function is done like this:
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentrun.cpp 6
+*/
+
+/*!
+ \fn QFuture<T> QtConcurrent::run(Function function, ...);
+ \relates <QtConcurrentRun>
+
+ Runs \a function in a separate thread. The thread is taken from the global
+ QThreadPool. Note that the function may not run immediately; the function
+ will only be run when a thread is available.
+
+ T is the same type as the return value of \a function. Non-void return
+ values can be accessed via the QFuture::result() function.
+
+ Note that the QFuture returned by QtConcurrent::run() does not support
+ canceling, pausing, or progress reporting. The QFuture returned can only
+ be used to query for the running/finished status and the return value of
+ the function.
+*/
diff --git a/src/corelib/concurrent/qtconcurrentrun.h b/src/corelib/concurrent/qtconcurrentrun.h
new file mode 100644
index 0000000000..9fa8a2797e
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrun.h
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Generated code, do not edit! Use generator at tools/qtconcurrent/generaterun/
+#ifndef QTCONCURRENT_RUN_H
+#define QTCONCURRENT_RUN_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qtconcurrentrunbase.h>
+#include <QtCore/qtconcurrentstoredfunctioncall.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifdef qdoc
+
+namespace QtConcurrent {
+
+ template <typename T>
+ QFuture<T> run(Function function, ...);
+
+} // namespace QtConcurrent
+
+#else
+
+namespace QtConcurrent {
+
+template <typename T>
+QFuture<T> run(T (*functionPointer)())
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall0<T, T (*)()>::type(functionPointer))->start();
+}
+template <typename T, typename Param1, typename Arg1>
+QFuture<T> run(T (*functionPointer)(Param1), const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall1<T, T (*)(Param1), Arg1>::type(functionPointer, arg1))->start();
+}
+template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(T (*functionPointer)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall2<T, T (*)(Param1, Param2), Arg1, Arg2>::type(functionPointer, arg1, arg2))->start();
+}
+template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(T (*functionPointer)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall3<T, T (*)(Param1, Param2, Param3), Arg1, Arg2, Arg3>::type(functionPointer, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(T (*functionPointer)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall4<T, T (*)(Param1, Param2, Param3, Param4), Arg1, Arg2, Arg3, Arg4>::type(functionPointer, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(T (*functionPointer)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall5<T, T (*)(Param1, Param2, Param3, Param4, Param5), Arg1, Arg2, Arg3, Arg4, Arg5>::type(functionPointer, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename FunctionObject>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall0<QT_TYPENAME FunctionObject::result_type, FunctionObject>::type(functionObject))->start();
+}
+template <typename FunctionObject, typename Arg1>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall1<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1>::type(functionObject, arg1))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall2<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2>::type(functionObject, arg1, arg2))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall3<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3>::type(functionObject, arg1, arg2, arg3))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall4<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4>::type(functionObject, arg1, arg2, arg3, arg4))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredFunctorCall5<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4, Arg5>::type(functionObject, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename FunctionObject>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall0<QT_TYPENAME FunctionObject::result_type, FunctionObject>::type(functionObject))->start();
+}
+template <typename FunctionObject, typename Arg1>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall1<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1>::type(functionObject, arg1))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall2<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2>::type(functionObject, arg1, arg2))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall3<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3>::type(functionObject, arg1, arg2, arg3))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall4<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4>::type(functionObject, arg1, arg2, arg3, arg4))->start();
+}
+template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredFunctorPointerCall5<QT_TYPENAME FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4, Arg5>::type(functionObject, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename T, typename Class>
+QFuture<T> run(const Class &object, T (Class::*fn)())
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall0<T, Class>::type(fn, object))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1), const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename T, typename Class>
+QFuture<T> run(const Class &object, T (Class::*fn)() const)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall0<T, Class>::type(fn, object))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1) const, const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2) const, const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename T, typename Class>
+QFuture<T> run(Class *object, T (Class::*fn)())
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall0<T, Class>::type(fn, object))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1), const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+template <typename T, typename Class>
+QFuture<T> run(const Class *object, T (Class::*fn)() const)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall0<T, Class>::type(fn, object))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1) const, const Arg1 &arg1)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2) const, const Arg1 &arg1, const Arg2 &arg2)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2, Param3) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start();
+}
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
+{
+ return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
+}
+
+} //namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentrunbase.h b/src/corelib/concurrent/qtconcurrentrunbase.h
new file mode 100644
index 0000000000..f26a3e3a30
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrunbase.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_RUNBASE_H
+#define QTCONCURRENT_RUNBASE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qfuture.h>
+#include <QtCore/qrunnable.h>
+#include <QtCore/qthreadpool.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+template <typename T>
+struct SelectSpecialization
+{
+ template <class Normal, class Void>
+ struct Type { typedef Normal type; };
+};
+
+template <>
+struct SelectSpecialization<void>
+{
+ template <class Normal, class Void>
+ struct Type { typedef Void type; };
+};
+
+template <typename T>
+class RunFunctionTaskBase : public QFutureInterface<T> , public QRunnable
+{
+public:
+ QFuture<T> start()
+ {
+ this->setRunnable(this);
+ this->reportStarted();
+ QFuture<T> future = this->future();
+ QThreadPool::globalInstance()->start(this, /*m_priority*/ 0);
+ return future;
+ }
+
+ void run() {}
+ virtual void runFunctor() = 0;
+};
+
+template <typename T>
+class RunFunctionTask : public RunFunctionTaskBase<T>
+{
+public:
+ void run()
+ {
+ if (this->isCanceled()) {
+ this->reportFinished();
+ return;
+ }
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ this->runFunctor();
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QtConcurrent::Exception &e) {
+ QFutureInterface<T>::reportException(e);
+ } catch (...) {
+ QFutureInterface<T>::reportException(QtConcurrent::UnhandledException());
+ }
+#endif
+
+ this->reportResult(result);
+ this->reportFinished();
+ }
+ T result;
+};
+
+template <>
+class RunFunctionTask<void> : public RunFunctionTaskBase<void>
+{
+public:
+ void run()
+ {
+ if (this->isCanceled()) {
+ this->reportFinished();
+ return;
+ }
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ this->runFunctor();
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QtConcurrent::Exception &e) {
+ QFutureInterface<void>::reportException(e);
+ } catch (...) {
+ QFutureInterface<void>::reportException(QtConcurrent::UnhandledException());
+ }
+#endif
+ this->reportFinished();
+ }
+};
+
+} //namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentstoredfunctioncall.h b/src/corelib/concurrent/qtconcurrentstoredfunctioncall.h
new file mode 100644
index 0000000000..82d95f6e21
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentstoredfunctioncall.h
@@ -0,0 +1,1328 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Generated code, do not edit! Use generator at tools/qtconcurrent/generaterun/
+#ifndef QTCONCURRENT_STOREDFUNCTIONCALL_H
+#define QTCONCURRENT_STOREDFUNCTIONCALL_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+#include <QtCore/qtconcurrentrunbase.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+template <typename T, typename FunctionPointer>
+struct StoredFunctorCall0: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall0(FunctionPointer _function)
+ : function(_function) {}
+ void runFunctor() { this->result = function(); }
+ FunctionPointer function;
+
+};
+
+template <typename T, typename FunctionPointer>
+struct VoidStoredFunctorCall0: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall0(FunctionPointer _function)
+ : function(_function) {}
+ void runFunctor() { function(); }
+ FunctionPointer function;
+
+};
+
+template <typename T, typename FunctionPointer>
+struct SelectStoredFunctorCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall0 <T, FunctionPointer>,
+ VoidStoredFunctorCall0<T, FunctionPointer> >::type type;
+};
+template <typename T, typename FunctionPointer>
+struct StoredFunctorPointerCall0: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall0(FunctionPointer * _function)
+ : function(_function) {}
+ void runFunctor() { this->result =(*function)(); }
+ FunctionPointer * function;
+
+};
+
+template <typename T, typename FunctionPointer>
+struct VoidStoredFunctorPointerCall0: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall0(FunctionPointer * _function)
+ : function(_function) {}
+ void runFunctor() {(*function)(); }
+ FunctionPointer * function;
+
+};
+
+template <typename T, typename FunctionPointer>
+struct SelectStoredFunctorPointerCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall0 <T, FunctionPointer>,
+ VoidStoredFunctorPointerCall0<T, FunctionPointer> >::type type;
+};
+template <typename T, typename Class>
+class StoredMemberFunctionCall0 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)();
+ }
+private:
+ T (Class::*fn)();
+ Class object;
+
+};
+template <typename T, typename Class>
+class VoidStoredMemberFunctionCall0 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ (object.*fn)();
+ }
+private:
+ T (Class::*fn)();
+ Class object;
+
+};
+template <typename T, typename Class>
+struct SelectStoredMemberFunctionCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall0 <T, Class>,
+ VoidStoredMemberFunctionCall0<T, Class> >::type type;
+};
+template <typename T, typename Class>
+class StoredConstMemberFunctionCall0 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall0(T (Class::*_fn)() const, const Class &_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)();
+ }
+private:
+ T (Class::*fn)()const;
+ const Class object;
+
+};
+template <typename T, typename Class>
+class VoidStoredConstMemberFunctionCall0 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall0(T (Class::*_fn)() const, const Class &_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ (object.*fn)();
+ }
+private:
+ T (Class::*fn)()const;
+ const Class object;
+
+};
+template <typename T, typename Class>
+struct SelectStoredConstMemberFunctionCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall0 <T, Class>,
+ VoidStoredConstMemberFunctionCall0<T, Class> >::type type;
+};
+template <typename T, typename Class>
+class StoredMemberFunctionPointerCall0 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall0(T (Class::*_fn)() , Class *_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)();
+ }
+private:
+ T (Class::*fn)();
+ Class *object;
+
+};
+template <typename T, typename Class>
+class VoidStoredMemberFunctionPointerCall0 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall0(T (Class::*_fn)() , Class *_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ (object->*fn)();
+ }
+private:
+ T (Class::*fn)();
+ Class *object;
+
+};
+template <typename T, typename Class>
+struct SelectStoredMemberFunctionPointerCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall0 <T, Class>,
+ VoidStoredMemberFunctionPointerCall0<T, Class> >::type type;
+};
+template <typename T, typename Class>
+class StoredConstMemberFunctionPointerCall0 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall0(T (Class::*_fn)() const, Class const *_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)();
+ }
+private:
+ T (Class::*fn)()const;
+ Class const *object;
+
+};
+template <typename T, typename Class>
+class VoidStoredConstMemberFunctionPointerCall0 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall0(T (Class::*_fn)() const, Class const *_object)
+ : fn(_fn), object(_object){ }
+
+ void runFunctor()
+ {
+ (object->*fn)();
+ }
+private:
+ T (Class::*fn)()const;
+ Class const *object;
+
+};
+template <typename T, typename Class>
+struct SelectStoredConstMemberFunctionPointerCall0
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall0 <T, Class>,
+ VoidStoredConstMemberFunctionPointerCall0<T, Class> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1>
+struct StoredFunctorCall1: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall1(FunctionPointer _function, const Arg1 &_arg1)
+ : function(_function), arg1(_arg1) {}
+ void runFunctor() { this->result = function(arg1); }
+ FunctionPointer function;
+ Arg1 arg1;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1>
+struct VoidStoredFunctorCall1: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall1(FunctionPointer _function, const Arg1 &_arg1)
+ : function(_function), arg1(_arg1) {}
+ void runFunctor() { function(arg1); }
+ FunctionPointer function;
+ Arg1 arg1;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1>
+struct SelectStoredFunctorCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall1 <T, FunctionPointer, Arg1>,
+ VoidStoredFunctorCall1<T, FunctionPointer, Arg1> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1>
+struct StoredFunctorPointerCall1: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall1(FunctionPointer * _function, const Arg1 &_arg1)
+ : function(_function), arg1(_arg1) {}
+ void runFunctor() { this->result =(*function)(arg1); }
+ FunctionPointer * function;
+ Arg1 arg1;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1>
+struct VoidStoredFunctorPointerCall1: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall1(FunctionPointer * _function, const Arg1 &_arg1)
+ : function(_function), arg1(_arg1) {}
+ void runFunctor() {(*function)(arg1); }
+ FunctionPointer * function;
+ Arg1 arg1;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1>
+struct SelectStoredFunctorPointerCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall1 <T, FunctionPointer, Arg1>,
+ VoidStoredFunctorPointerCall1<T, FunctionPointer, Arg1> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class StoredMemberFunctionCall1 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall1(T (Class::*_fn)(Param1) , const Class &_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1);
+ Class object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class VoidStoredMemberFunctionCall1 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall1(T (Class::*_fn)(Param1) , const Class &_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1);
+ Class object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+struct SelectStoredMemberFunctionCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall1 <T, Class, Param1, Arg1>,
+ VoidStoredMemberFunctionCall1<T, Class, Param1, Arg1> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class StoredConstMemberFunctionCall1 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall1(T (Class::*_fn)(Param1) const, const Class &_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1)const;
+ const Class object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class VoidStoredConstMemberFunctionCall1 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall1(T (Class::*_fn)(Param1) const, const Class &_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1)const;
+ const Class object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+struct SelectStoredConstMemberFunctionCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall1 <T, Class, Param1, Arg1>,
+ VoidStoredConstMemberFunctionCall1<T, Class, Param1, Arg1> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class StoredMemberFunctionPointerCall1 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall1(T (Class::*_fn)(Param1) , Class *_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1);
+ Class *object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class VoidStoredMemberFunctionPointerCall1 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall1(T (Class::*_fn)(Param1) , Class *_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1);
+ Class *object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+struct SelectStoredMemberFunctionPointerCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall1 <T, Class, Param1, Arg1>,
+ VoidStoredMemberFunctionPointerCall1<T, Class, Param1, Arg1> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class StoredConstMemberFunctionPointerCall1 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall1(T (Class::*_fn)(Param1) const, Class const *_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1)const;
+ Class const *object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+class VoidStoredConstMemberFunctionPointerCall1 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall1(T (Class::*_fn)(Param1) const, Class const *_object, const Arg1 &_arg1)
+ : fn(_fn), object(_object), arg1(_arg1){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1);
+ }
+private:
+ T (Class::*fn)(Param1)const;
+ Class const *object;
+ Arg1 arg1;
+};
+template <typename T, typename Class, typename Param1, typename Arg1>
+struct SelectStoredConstMemberFunctionPointerCall1
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall1 <T, Class, Param1, Arg1>,
+ VoidStoredConstMemberFunctionPointerCall1<T, Class, Param1, Arg1> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct StoredFunctorCall2: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall2(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2)
+ : function(_function), arg1(_arg1), arg2(_arg2) {}
+ void runFunctor() { this->result = function(arg1, arg2); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct VoidStoredFunctorCall2: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall2(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2)
+ : function(_function), arg1(_arg1), arg2(_arg2) {}
+ void runFunctor() { function(arg1, arg2); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct SelectStoredFunctorCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall2 <T, FunctionPointer, Arg1, Arg2>,
+ VoidStoredFunctorCall2<T, FunctionPointer, Arg1, Arg2> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct StoredFunctorPointerCall2: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall2(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2)
+ : function(_function), arg1(_arg1), arg2(_arg2) {}
+ void runFunctor() { this->result =(*function)(arg1, arg2); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct VoidStoredFunctorPointerCall2: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall2(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2)
+ : function(_function), arg1(_arg1), arg2(_arg2) {}
+ void runFunctor() {(*function)(arg1, arg2); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
+struct SelectStoredFunctorPointerCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall2 <T, FunctionPointer, Arg1, Arg2>,
+ VoidStoredFunctorPointerCall2<T, FunctionPointer, Arg1, Arg2> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class StoredMemberFunctionCall2 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2);
+ Class object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class VoidStoredMemberFunctionCall2 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2);
+ Class object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+struct SelectStoredMemberFunctionCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall2 <T, Class, Param1, Arg1, Param2, Arg2>,
+ VoidStoredMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class StoredConstMemberFunctionCall2 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class VoidStoredConstMemberFunctionCall2 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+struct SelectStoredConstMemberFunctionCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall2 <T, Class, Param1, Arg1, Param2, Arg2>,
+ VoidStoredConstMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class StoredMemberFunctionPointerCall2 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2);
+ Class *object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class VoidStoredMemberFunctionPointerCall2 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2);
+ Class *object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+struct SelectStoredMemberFunctionPointerCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall2 <T, Class, Param1, Arg1, Param2, Arg2>,
+ VoidStoredMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class StoredConstMemberFunctionPointerCall2 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+class VoidStoredConstMemberFunctionPointerCall2 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2);
+ }
+private:
+ T (Class::*fn)(Param1, Param2)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
+struct SelectStoredConstMemberFunctionPointerCall2
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall2 <T, Class, Param1, Arg1, Param2, Arg2>,
+ VoidStoredConstMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct StoredFunctorCall3: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall3(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3) {}
+ void runFunctor() { this->result = function(arg1, arg2, arg3); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct VoidStoredFunctorCall3: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall3(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3) {}
+ void runFunctor() { function(arg1, arg2, arg3); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct SelectStoredFunctorCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall3 <T, FunctionPointer, Arg1, Arg2, Arg3>,
+ VoidStoredFunctorCall3<T, FunctionPointer, Arg1, Arg2, Arg3> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct StoredFunctorPointerCall3: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall3(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3) {}
+ void runFunctor() { this->result =(*function)(arg1, arg2, arg3); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct VoidStoredFunctorPointerCall3: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall3(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3) {}
+ void runFunctor() {(*function)(arg1, arg2, arg3); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
+struct SelectStoredFunctorPointerCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall3 <T, FunctionPointer, Arg1, Arg2, Arg3>,
+ VoidStoredFunctorPointerCall3<T, FunctionPointer, Arg1, Arg2, Arg3> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class StoredMemberFunctionCall3 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class VoidStoredMemberFunctionCall3 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+struct SelectStoredMemberFunctionCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall3 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>,
+ VoidStoredMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class StoredConstMemberFunctionCall3 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class VoidStoredConstMemberFunctionCall3 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+struct SelectStoredConstMemberFunctionCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall3 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>,
+ VoidStoredConstMemberFunctionCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class StoredMemberFunctionPointerCall3 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class VoidStoredMemberFunctionPointerCall3 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+struct SelectStoredMemberFunctionPointerCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall3 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>,
+ VoidStoredMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class StoredConstMemberFunctionPointerCall3 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+class VoidStoredConstMemberFunctionPointerCall3 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
+struct SelectStoredConstMemberFunctionPointerCall3
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall3 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>,
+ VoidStoredConstMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct StoredFunctorCall4: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall4(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) {}
+ void runFunctor() { this->result = function(arg1, arg2, arg3, arg4); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct VoidStoredFunctorCall4: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall4(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) {}
+ void runFunctor() { function(arg1, arg2, arg3, arg4); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct SelectStoredFunctorCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall4 <T, FunctionPointer, Arg1, Arg2, Arg3, Arg4>,
+ VoidStoredFunctorCall4<T, FunctionPointer, Arg1, Arg2, Arg3, Arg4> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct StoredFunctorPointerCall4: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall4(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) {}
+ void runFunctor() { this->result =(*function)(arg1, arg2, arg3, arg4); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct VoidStoredFunctorPointerCall4: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall4(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) {}
+ void runFunctor() {(*function)(arg1, arg2, arg3, arg4); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct SelectStoredFunctorPointerCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall4 <T, FunctionPointer, Arg1, Arg2, Arg3, Arg4>,
+ VoidStoredFunctorPointerCall4<T, FunctionPointer, Arg1, Arg2, Arg3, Arg4> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class StoredMemberFunctionCall4 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class VoidStoredMemberFunctionCall4 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+struct SelectStoredMemberFunctionCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall4 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>,
+ VoidStoredMemberFunctionCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class StoredConstMemberFunctionCall4 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class VoidStoredConstMemberFunctionCall4 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+struct SelectStoredConstMemberFunctionCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall4 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>,
+ VoidStoredConstMemberFunctionCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class StoredMemberFunctionPointerCall4 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class VoidStoredMemberFunctionPointerCall4 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+struct SelectStoredMemberFunctionPointerCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall4 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>,
+ VoidStoredMemberFunctionPointerCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class StoredConstMemberFunctionPointerCall4 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+class VoidStoredConstMemberFunctionPointerCall4 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3, arg4);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
+struct SelectStoredConstMemberFunctionPointerCall4
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall4 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>,
+ VoidStoredConstMemberFunctionPointerCall4<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct StoredFunctorCall5: public RunFunctionTask<T>
+{
+ inline StoredFunctorCall5(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {}
+ void runFunctor() { this->result = function(arg1, arg2, arg3, arg4, arg5); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct VoidStoredFunctorCall5: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorCall5(FunctionPointer _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {}
+ void runFunctor() { function(arg1, arg2, arg3, arg4, arg5); }
+ FunctionPointer function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct SelectStoredFunctorCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorCall5 <T, FunctionPointer, Arg1, Arg2, Arg3, Arg4, Arg5>,
+ VoidStoredFunctorCall5<T, FunctionPointer, Arg1, Arg2, Arg3, Arg4, Arg5> >::type type;
+};
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct StoredFunctorPointerCall5: public RunFunctionTask<T>
+{
+ inline StoredFunctorPointerCall5(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {}
+ void runFunctor() { this->result =(*function)(arg1, arg2, arg3, arg4, arg5); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct VoidStoredFunctorPointerCall5: public RunFunctionTask<T>
+{
+ inline VoidStoredFunctorPointerCall5(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {}
+ void runFunctor() {(*function)(arg1, arg2, arg3, arg4, arg5); }
+ FunctionPointer * function;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+
+template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+struct SelectStoredFunctorPointerCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredFunctorPointerCall5 <T, FunctionPointer, Arg1, Arg2, Arg3, Arg4, Arg5>,
+ VoidStoredFunctorPointerCall5<T, FunctionPointer, Arg1, Arg2, Arg3, Arg4, Arg5> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class StoredMemberFunctionCall5 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class VoidStoredMemberFunctionCall5 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5);
+ Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+struct SelectStoredMemberFunctionCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionCall5 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>,
+ VoidStoredMemberFunctionCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class StoredConstMemberFunctionCall5 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ this->result = (object.*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class VoidStoredConstMemberFunctionCall5 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) const, const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ (object.*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const;
+ const Class object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+struct SelectStoredConstMemberFunctionCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionCall5 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>,
+ VoidStoredConstMemberFunctionCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class StoredMemberFunctionPointerCall5 : public RunFunctionTask<T>
+{
+public:
+ StoredMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class VoidStoredMemberFunctionPointerCall5 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5);
+ Class *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+struct SelectStoredMemberFunctionPointerCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredMemberFunctionPointerCall5 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>,
+ VoidStoredMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5> >::type type;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class StoredConstMemberFunctionPointerCall5 : public RunFunctionTask<T>
+{
+public:
+ StoredConstMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ this->result = (object->*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+class VoidStoredConstMemberFunctionPointerCall5 : public RunFunctionTask<T>
+{
+public:
+ VoidStoredConstMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) const, Class const *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5)
+ : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ }
+
+ void runFunctor()
+ {
+ (object->*fn)(arg1, arg2, arg3, arg4, arg5);
+ }
+private:
+ T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const;
+ Class const *object;
+ Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
+};
+template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
+struct SelectStoredConstMemberFunctionPointerCall5
+{
+ typedef typename SelectSpecialization<T>::template
+ Type<StoredConstMemberFunctionPointerCall5 <T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>,
+ VoidStoredConstMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5> >::type type;
+};
+} //namespace QtConcurrent
+
+#endif // qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.cpp b/src/corelib/concurrent/qtconcurrentthreadengine.cpp
new file mode 100644
index 0000000000..db6217b83a
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentthreadengine.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentthreadengine.h"
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_NAMESPACE
+
+namespace QtConcurrent {
+
+ThreadEngineBarrier::ThreadEngineBarrier()
+:count(0) { }
+
+void ThreadEngineBarrier::acquire()
+{
+ forever {
+ int localCount = int(count);
+ if (localCount < 0) {
+ if (count.testAndSetOrdered(localCount, localCount -1))
+ return;
+ } else {
+ if (count.testAndSetOrdered(localCount, localCount + 1))
+ return;
+ }
+ }
+}
+
+int ThreadEngineBarrier::release()
+{
+ forever {
+ int localCount = int(count);
+ if (localCount == -1) {
+ if (count.testAndSetOrdered(-1, 0)) {
+ semaphore.release();
+ return 0;
+ }
+ } else if (localCount < 0) {
+ if (count.testAndSetOrdered(localCount, localCount + 1))
+ return qAbs(localCount + 1);
+ } else {
+ if (count.testAndSetOrdered(localCount, localCount - 1))
+ return localCount - 1;
+ }
+ }
+}
+
+// Wait until all threads have been released
+void ThreadEngineBarrier::wait()
+{
+ forever {
+ int localCount = int(count);
+ if (localCount == 0)
+ return;
+
+ Q_ASSERT(localCount > 0); // multiple waiters are not allowed.
+ if (count.testAndSetOrdered(localCount, -localCount)) {
+ semaphore.acquire();
+ return;
+ }
+ }
+}
+
+int ThreadEngineBarrier::currentCount()
+{
+ return int(count);
+}
+
+// releases a thread, unless this is the last thread.
+// returns true if the thread was released.
+bool ThreadEngineBarrier::releaseUnlessLast()
+{
+ forever {
+ int localCount = int(count);
+ if (qAbs(localCount) == 1) {
+ return false;
+ } else if (localCount < 0) {
+ if (count.testAndSetOrdered(localCount, localCount + 1))
+ return true;
+ } else {
+ if (count.testAndSetOrdered(localCount, localCount - 1))
+ return true;
+ }
+ }
+}
+
+ThreadEngineBase::ThreadEngineBase()
+:futureInterface(0), threadPool(QThreadPool::globalInstance())
+{
+ setAutoDelete(false);
+}
+
+ThreadEngineBase::~ThreadEngineBase() {}
+
+void ThreadEngineBase::startSingleThreaded()
+{
+ start();
+ while (threadFunction() != ThreadFinished)
+ ;
+ finish();
+}
+
+void ThreadEngineBase::startBlocking()
+{
+ start();
+ barrier.acquire();
+ startThreads();
+
+ bool throttled = false;
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ while (threadFunction() == ThrottleThread) {
+ if (threadThrottleExit()) {
+ throttled = true;
+ break;
+ }
+ }
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QtConcurrent::Exception &e) {
+ handleException(e);
+ } catch (...) {
+ handleException(QtConcurrent::UnhandledException());
+ }
+#endif
+
+ if (throttled == false) {
+ barrier.release();
+ }
+
+ barrier.wait();
+ finish();
+ exceptionStore.throwPossibleException();
+}
+
+void ThreadEngineBase::startThread()
+{
+ startThreadInternal();
+}
+
+void ThreadEngineBase::acquireBarrierSemaphore()
+{
+ barrier.acquire();
+}
+
+bool ThreadEngineBase::isCanceled()
+{
+ if (futureInterface)
+ return futureInterface->isCanceled();
+ else
+ return false;
+}
+
+void ThreadEngineBase::waitForResume()
+{
+ if (futureInterface)
+ futureInterface->waitForResume();
+}
+
+bool ThreadEngineBase::isProgressReportingEnabled()
+{
+ // If we don't have a QFuture, there is no-one to report the progress to.
+ return (futureInterface != 0);
+}
+
+void ThreadEngineBase::setProgressValue(int progress)
+{
+ if (futureInterface)
+ futureInterface->setProgressValue(progress);
+}
+
+void ThreadEngineBase::setProgressRange(int minimum, int maximum)
+{
+ if (futureInterface)
+ futureInterface->setProgressRange(minimum, maximum);
+}
+
+bool ThreadEngineBase::startThreadInternal()
+{
+ if (this->isCanceled())
+ return false;
+
+ barrier.acquire();
+ if (!threadPool->tryStart(this)) {
+ barrier.release();
+ return false;
+ }
+ return true;
+}
+
+void ThreadEngineBase::startThreads()
+{
+ while (shouldStartThread() && startThreadInternal())
+ ;
+}
+
+void ThreadEngineBase::threadExit()
+{
+ const bool asynchronous = futureInterface != 0;
+ const int lastThread = (barrier.release() == 0);
+
+ if (lastThread && asynchronous)
+ this->asynchronousFinish();
+}
+
+// Called by a worker thread that wants to be throttled. If the current number
+// of running threads is larger than one the thread is allowed to exit and
+// this function returns one.
+bool ThreadEngineBase::threadThrottleExit()
+{
+ return barrier.releaseUnlessLast();
+}
+
+void ThreadEngineBase::run() // implements QRunnable.
+{
+ if (this->isCanceled()) {
+ threadExit();
+ return;
+ }
+
+ startThreads();
+
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ while (threadFunction() == ThrottleThread) {
+ // threadFunction returning ThrottleThread means it that the user
+ // struct wants to be throttled by making a worker thread exit.
+ // Respect that request unless this is the only worker thread left
+ // running, in which case it has to keep going.
+ if (threadThrottleExit())
+ return;
+ }
+
+#ifndef QT_NO_EXCEPTIONS
+ } catch (QtConcurrent::Exception &e) {
+ handleException(e);
+ } catch (...) {
+ handleException(QtConcurrent::UnhandledException());
+ }
+#endif
+ threadExit();
+}
+
+#ifndef QT_NO_EXCEPTIONS
+
+void ThreadEngineBase::handleException(const QtConcurrent::Exception &exception)
+{
+ if (futureInterface)
+ futureInterface->reportException(exception);
+ else
+ exceptionStore.setException(exception);
+}
+#endif
+
+
+} // namepsace QtConcurrent
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CONCURRENT
diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.h b/src/corelib/concurrent/qtconcurrentthreadengine.h
new file mode 100644
index 0000000000..e07dd37c9f
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentthreadengine.h
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCONCURRENT_THREADENGINE_H
+#define QTCONCURRENT_THREADENGINE_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_CONCURRENT
+
+#include <QtCore/qthreadpool.h>
+#include <QtCore/qfuture.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qtconcurrentexception.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qatomic.h>
+#include <QtCore/qsemaphore.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+// The ThreadEngineBarrier counts worker threads, and allows one
+// thread to wait for all others to finish. Tested for its use in
+// QtConcurrent, requires more testing for use as a general class.
+class ThreadEngineBarrier
+{
+private:
+ // The thread count is maintained as an integer in the count atomic
+ // variable. The count can be either positive or negative - a negative
+ // count signals that a thread is waiting on the barrier.
+
+ // BC note: inlined code from Qt < 4.6 will expect to find the QMutex
+ // and QAtomicInt here. ### Qt 5: remove.
+ QMutex mutex;
+ QAtomicInt count;
+
+ QSemaphore semaphore;
+public:
+ ThreadEngineBarrier();
+ void acquire();
+ int release();
+ void wait();
+ int currentCount();
+ bool releaseUnlessLast();
+};
+
+enum ThreadFunctionResult { ThrottleThread, ThreadFinished };
+
+// The ThreadEngine controls the threads used in the computation.
+// Can be run in three modes: single threaded, multi-threaded blocking
+// and multi-threaded asynchronous.
+// The code for the single threaded mode is
+class Q_CORE_EXPORT ThreadEngineBase: public QRunnable
+{
+public:
+ // Public API:
+ ThreadEngineBase();
+ virtual ~ThreadEngineBase();
+ void startSingleThreaded();
+ void startBlocking();
+ void startThread();
+ bool isCanceled();
+ void waitForResume();
+ bool isProgressReportingEnabled();
+ void setProgressValue(int progress);
+ void setProgressRange(int minimum, int maximum);
+ void acquireBarrierSemaphore();
+
+protected: // The user overrides these:
+ virtual void start() {}
+ virtual void finish() {}
+ virtual ThreadFunctionResult threadFunction() { return ThreadFinished; }
+ virtual bool shouldStartThread() { return futureInterface ? !futureInterface->isPaused() : true; }
+ virtual bool shouldThrottleThread() { return futureInterface ? futureInterface->isPaused() : false; }
+private:
+ bool startThreadInternal();
+ void startThreads();
+ void threadExit();
+ bool threadThrottleExit();
+ void run();
+ virtual void asynchronousFinish() = 0;
+#ifndef QT_NO_EXCEPTIONS
+ void handleException(const QtConcurrent::Exception &exception);
+#endif
+protected:
+ QFutureInterfaceBase *futureInterface;
+ QThreadPool *threadPool;
+ ThreadEngineBarrier barrier;
+ QtConcurrent::internal::ExceptionStore exceptionStore;
+};
+
+
+template <typename T>
+class ThreadEngine : public virtual ThreadEngineBase
+{
+public:
+ typedef T ResultType;
+
+ virtual T *result() { return 0; }
+
+ QFutureInterface<T> *futureInterfaceTyped()
+ {
+ return static_cast<QFutureInterface<T> *>(futureInterface);
+ }
+
+ // Runs the user algorithm using a single thread.
+ T *startSingleThreaded()
+ {
+ ThreadEngineBase::startSingleThreaded();
+ return result();
+ }
+
+ // Runs the user algorithm using multiple threads.
+ // This function blocks until the algorithm is finished,
+ // and then returns the result.
+ T *startBlocking()
+ {
+ ThreadEngineBase::startBlocking();
+ return result();
+ }
+
+ // Runs the user algorithm using multiple threads.
+ // Does not block, returns a future.
+ QFuture<T> startAsynchronously()
+ {
+ futureInterface = new QFutureInterface<T>();
+
+ // reportStart() must be called before starting threads, otherwise the
+ // user algorithm might finish while reportStart() is running, which
+ // is very bad.
+ futureInterface->reportStarted();
+ QFuture<T> future = QFuture<T>(futureInterfaceTyped());
+ start();
+
+ acquireBarrierSemaphore();
+ threadPool->start(this);
+ return future;
+ }
+
+ void asynchronousFinish()
+ {
+ finish();
+ futureInterfaceTyped()->reportFinished(result());
+ delete futureInterfaceTyped();
+ delete this;
+ }
+
+
+ void reportResult(const T *_result, int index = -1)
+ {
+ if (futureInterface)
+ futureInterfaceTyped()->reportResult(_result, index);
+ }
+
+ void reportResults(const QVector<T> &_result, int index = -1, int count = -1)
+ {
+ if (futureInterface)
+ futureInterfaceTyped()->reportResults(_result, index, count);
+ }
+};
+
+// The ThreadEngineStarter class ecapsulates the return type
+// from the thread engine.
+// Depending on how the it is used, it will run
+// the engine in either blocking mode or asynchronous mode.
+template <typename T>
+class ThreadEngineStarterBase
+{
+public:
+ ThreadEngineStarterBase(ThreadEngine<T> *_threadEngine)
+ : threadEngine(_threadEngine) { }
+
+ inline ThreadEngineStarterBase(const ThreadEngineStarterBase &other)
+ : threadEngine(other.threadEngine) { }
+
+ QFuture<T> startAsynchronously()
+ {
+ return threadEngine->startAsynchronously();
+ }
+
+ operator QFuture<T>()
+ {
+ return startAsynchronously();
+ }
+
+protected:
+ ThreadEngine<T> *threadEngine;
+};
+
+
+// We need to factor out the code that dereferences the T pointer,
+// with a specialization where T is void. (code that dereferences a void *
+// won't compile)
+template <typename T>
+class ThreadEngineStarter : public ThreadEngineStarterBase<T>
+{
+ typedef ThreadEngineStarterBase<T> Base;
+ typedef ThreadEngine<T> TypedThreadEngine;
+public:
+ ThreadEngineStarter(TypedThreadEngine *eng)
+ : Base(eng) { }
+
+ T startBlocking()
+ {
+ T t = *this->threadEngine->startBlocking();
+ delete this->threadEngine;
+ return t;
+ }
+};
+
+// Full template specialization where T is void.
+template <>
+class ThreadEngineStarter<void> : public ThreadEngineStarterBase<void>
+{
+public:
+ ThreadEngineStarter<void>(ThreadEngine<void> *_threadEngine)
+ :ThreadEngineStarterBase<void>(_threadEngine) {}
+
+ void startBlocking()
+ {
+ this->threadEngine->startBlocking();
+ delete this->threadEngine;
+ }
+};
+
+template <typename ThreadEngine>
+inline ThreadEngineStarter<typename ThreadEngine::ResultType> startThreadEngine(ThreadEngine *threadEngine)
+{
+ return ThreadEngineStarter<typename ThreadEngine::ResultType>(threadEngine);
+}
+
+} // namespace QtConcurrent
+
+#endif //qdoc
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_CONCURRENT
+
+#endif
diff --git a/src/corelib/concurrent/qthreadpool.cpp b/src/corelib/concurrent/qthreadpool.cpp
new file mode 100644
index 0000000000..1a07b5bc8e
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool.cpp
@@ -0,0 +1,651 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthreadpool.h"
+#include "qthreadpool_p.h"
+#include "qelapsedtimer.h"
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+inline bool operator<(int priority, const QPair<QRunnable *, int> &p)
+{
+ return p.second < priority;
+}
+inline bool operator<(const QPair<QRunnable *, int> &p, int priority)
+{
+ return priority < p.second;
+}
+
+Q_GLOBAL_STATIC(QThreadPool, theInstance)
+
+/*
+ QThread wrapper, provides synchronizitaion against a ThreadPool
+*/
+class QThreadPoolThread : public QThread
+{
+public:
+ QThreadPoolThread(QThreadPoolPrivate *manager);
+ void run();
+ void registerTheadInactive();
+
+ QThreadPoolPrivate *manager;
+ QRunnable *runnable;
+};
+
+/*
+ QThreadPool private class.
+*/
+
+
+/*!\internal
+
+*/
+QThreadPoolThread::QThreadPoolThread(QThreadPoolPrivate *manager)
+ :manager(manager), runnable(0)
+{ }
+
+/* \internal
+
+*/
+void QThreadPoolThread::run()
+{
+ QMutexLocker locker(&manager->mutex);
+ for(;;) {
+ QRunnable *r = runnable;
+ runnable = 0;
+
+ do {
+ if (r) {
+ const bool autoDelete = r->autoDelete();
+
+
+ // run the task
+ locker.unlock();
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ r->run();
+#ifndef QT_NO_EXCEPTIONS
+ } catch (...) {
+ qWarning("Qt Concurrent has caught an exception thrown from a worker thread.\n"
+ "This is not supported, exceptions thrown in worker threads must be\n"
+ "caught before control returns to Qt Concurrent.");
+ registerTheadInactive();
+ throw;
+ }
+#endif
+ locker.relock();
+
+ if (autoDelete && !--r->ref)
+ delete r;
+ }
+
+ // if too many threads are active, expire this thread
+ if (manager->tooManyThreadsActive())
+ break;
+
+ r = !manager->queue.isEmpty() ? manager->queue.takeFirst().first : 0;
+ } while (r != 0);
+
+ if (manager->isExiting) {
+ registerTheadInactive();
+ break;
+ }
+
+ // if too many threads are active, expire this thread
+ bool expired = manager->tooManyThreadsActive();
+ if (!expired) {
+ ++manager->waitingThreads;
+ registerTheadInactive();
+ // wait for work, exiting after the expiry timeout is reached
+ expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout);
+ ++manager->activeThreads;
+
+ if (expired)
+ --manager->waitingThreads;
+ }
+ if (expired) {
+ manager->expiredThreads.enqueue(this);
+ registerTheadInactive();
+ break;
+ }
+ }
+}
+
+void QThreadPoolThread::registerTheadInactive()
+{
+ if (--manager->activeThreads == 0)
+ manager->noActiveThreads.wakeAll();
+}
+
+
+/* \internal
+
+*/
+QThreadPoolPrivate:: QThreadPoolPrivate()
+ : isExiting(false),
+ expiryTimeout(30000),
+ maxThreadCount(qAbs(QThread::idealThreadCount())),
+ reservedThreads(0),
+ waitingThreads(0),
+ activeThreads(0)
+{ }
+
+bool QThreadPoolPrivate::tryStart(QRunnable *task)
+{
+ if (allThreads.isEmpty()) {
+ // always create at least one thread
+ startThread(task);
+ return true;
+ }
+
+ // can't do anything if we're over the limit
+ if (activeThreadCount() >= maxThreadCount)
+ return false;
+
+ if (waitingThreads > 0) {
+ // recycle an available thread
+ --waitingThreads;
+ enqueueTask(task);
+ return true;
+ }
+
+ if (!expiredThreads.isEmpty()) {
+ // restart an expired thread
+ QThreadPoolThread *thread = expiredThreads.dequeue();
+ Q_ASSERT(thread->runnable == 0);
+
+ ++activeThreads;
+
+ if (task->autoDelete())
+ ++task->ref;
+ thread->runnable = task;
+ thread->start();
+ return true;
+ }
+
+ // start a new thread
+ startThread(task);
+ return true;
+}
+
+void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
+{
+ if (runnable->autoDelete())
+ ++runnable->ref;
+
+ // put it on the queue
+ QList<QPair<QRunnable *, int> >::iterator at =
+ qUpperBound(queue.begin(), queue.end(), priority);
+ queue.insert(at, qMakePair(runnable, priority));
+ runnableReady.wakeOne();
+}
+
+int QThreadPoolPrivate::activeThreadCount() const
+{
+ // To improve scalability this function is called without holding
+ // the mutex lock -- keep it thread-safe.
+ return (allThreads.count()
+ - expiredThreads.count()
+ - waitingThreads
+ + reservedThreads);
+}
+
+void QThreadPoolPrivate::tryToStartMoreThreads()
+{
+ // try to push tasks on the queue to any available threads
+ while (!queue.isEmpty() && tryStart(queue.first().first))
+ queue.removeFirst();
+}
+
+bool QThreadPoolPrivate::tooManyThreadsActive() const
+{
+ const int activeThreadCount = this->activeThreadCount();
+ return activeThreadCount > maxThreadCount && (activeThreadCount - reservedThreads) > 1;
+}
+
+/*! \internal
+
+*/
+void QThreadPoolPrivate::startThread(QRunnable *runnable)
+{
+ QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));
+ thread->setObjectName(QLatin1String("Thread (pooled)"));
+ allThreads.insert(thread.data());
+ ++activeThreads;
+
+ if (runnable->autoDelete())
+ ++runnable->ref;
+ thread->runnable = runnable;
+ thread.take()->start();
+}
+
+/*! \internal
+ Makes all threads exit, waits for each tread to exit and deletes it.
+*/
+void QThreadPoolPrivate::reset()
+{
+ QMutexLocker locker(&mutex);
+ isExiting = true;
+ runnableReady.wakeAll();
+
+ do {
+ // make a copy of the set so that we can iterate without the lock
+ QSet<QThreadPoolThread *> allThreadsCopy = allThreads;
+ allThreads.clear();
+ locker.unlock();
+
+ foreach (QThreadPoolThread *thread, allThreadsCopy) {
+ thread->wait();
+ delete thread;
+ }
+
+ locker.relock();
+ // repeat until all newly arrived threads have also completed
+ } while (!allThreads.isEmpty());
+
+ waitingThreads = 0;
+ expiredThreads.clear();
+
+ isExiting = false;
+}
+
+bool QThreadPoolPrivate::waitForDone(int msecs)
+{
+ QMutexLocker locker(&mutex);
+ if (msecs < 0) {
+ while (!(queue.isEmpty() && activeThreads == 0))
+ noActiveThreads.wait(locker.mutex());
+ } else {
+ QElapsedTimer timer;
+ timer.start();
+ int t;
+ while (!(queue.isEmpty() && activeThreads == 0) &&
+ ((t = msecs - timer.elapsed()) > 0))
+ noActiveThreads.wait(locker.mutex(), t);
+ }
+ return queue.isEmpty() && activeThreads == 0;
+}
+
+/*! \internal
+ Pulls a runnable from the front queue and runs it in the current thread. Blocks
+ until the runnable has completed. Returns true if a runnable was found.
+*/
+bool QThreadPoolPrivate::startFrontRunnable()
+{
+ QMutexLocker locker(&mutex);
+ if (queue.isEmpty())
+ return false;
+
+ QRunnable *runnable = queue.takeFirst().first;
+ const bool autoDelete = runnable->autoDelete();
+ bool del = autoDelete && !--runnable->ref;
+
+ locker.unlock();
+ runnable->run();
+ locker.relock();
+
+ if (del) {
+ delete runnable;
+ }
+
+ return true;
+}
+
+/*! \internal
+ Seaches for \a runnable in the queue, removes it from the queue and
+ runs it if found. This functon does not return until the runnable
+ has completed.
+*/
+void QThreadPoolPrivate::stealRunnable(QRunnable *runnable)
+{
+ if (runnable == 0 || queue.isEmpty())
+ return;
+ bool found = false;
+ {
+ QMutexLocker locker(&mutex);
+ QList<QPair<QRunnable *, int> >::iterator it = queue.begin();
+ QList<QPair<QRunnable *, int> >::iterator end = queue.end();
+
+ while (it != end) {
+ if (it->first == runnable) {
+ found = true;
+ queue.erase(it);
+ break;
+ }
+ ++it;
+ }
+ }
+
+ if (!found)
+ return;
+
+ const bool autoDelete = runnable->autoDelete();
+ bool del = autoDelete && !--runnable->ref;
+
+ runnable->run();
+
+ if (del) {
+ delete runnable;
+ }
+}
+
+/*!
+ \class QThreadPool
+ \brief The QThreadPool class manages a collection of QThreads.
+ \since 4.4
+ \threadsafe
+
+ \ingroup thread
+
+ QThreadPool manages and recyles individual QThread objects to help reduce
+ thread creation costs in programs that use threads. Each Qt application
+ has one global QThreadPool object, which can be accessed by calling
+ globalInstance().
+
+ To use one of the QThreadPool threads, subclass QRunnable and implement
+ the run() virtual function. Then create an object of that class and pass
+ it to QThreadPool::start().
+
+ \snippet doc/src/snippets/code/src_corelib_concurrent_qthreadpool.cpp 0
+
+ QThreadPool deletes the QRunnable automatically by default. Use
+ QRunnable::setAutoDelete() to change the auto-deletion flag.
+
+ QThreadPool supports executing the same QRunnable more than once
+ by calling tryStart(this) from within QRunnable::run().
+ If autoDelete is enabled the QRunnable will be deleted when
+ the last thread exits the run function. Calling start()
+ multiple times with the same QRunnable when autoDelete is enabled
+ creates a race condition and is not recommended.
+
+ Threads that are unused for a certain amount of time will expire. The
+ default expiry timeout is 30000 milliseconds (30 seconds). This can be
+ changed using setExpiryTimeout(). Setting a negative expiry timeout
+ disables the expiry mechanism.
+
+ Call maxThreadCount() to query the maximum number of threads to be used.
+ If needed, you can change the limit with setMaxThreadCount(). The default
+ maxThreadCount() is QThread::idealThreadCount(). The activeThreadCount()
+ function returns the number of threads currently doing work.
+
+ The reserveThread() function reserves a thread for external
+ use. Use releaseThread() when your are done with the thread, so
+ that it may be reused. Essentially, these functions temporarily
+ increase or reduce the active thread count and are useful when
+ implementing time-consuming operations that are not visible to the
+ QThreadPool.
+
+ Note that QThreadPool is a low-level class for managing threads, see
+ QtConcurrent::run() or the other
+ \l {Concurrent Programming}{Qt Concurrent} APIs for higher
+ level alternatives.
+
+ \sa QRunnable
+*/
+
+/*!
+ Constructs a thread pool with the given \a parent.
+*/
+QThreadPool::QThreadPool(QObject *parent)
+ : QObject(*new QThreadPoolPrivate, parent)
+{ }
+
+/*!
+ Destroys the QThreadPool.
+ This function will block until all runnables have been completed.
+*/
+QThreadPool::~QThreadPool()
+{
+ d_func()->waitForDone();
+ d_func()->reset();
+}
+
+/*!
+ Returns the global QThreadPool instance.
+*/
+QThreadPool *QThreadPool::globalInstance()
+{
+ return theInstance();
+}
+
+/*!
+ Reserves a thread and uses it to run \a runnable, unless this thread will
+ make the current thread count exceed maxThreadCount(). In that case,
+ \a runnable is added to a run queue instead. The \a priority argument can
+ be used to control the run queue's order of execution.
+
+ Note that the thread pool takes ownership of the \a runnable if
+ \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns true,
+ and the \a runnable will be deleted automatically by the thread
+ pool after the \l{QRunnable::run()}{runnable->run()} returns. If
+ \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns false,
+ ownership of \a runnable remains with the caller. Note that
+ changing the auto-deletion on \a runnable after calling this
+ functions results in undefined behavior.
+*/
+void QThreadPool::start(QRunnable *runnable, int priority)
+{
+ if (!runnable)
+ return;
+
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ if (!d->tryStart(runnable))
+ d->enqueueTask(runnable, priority);
+}
+
+/*!
+ Attempts to reserve a thread to run \a runnable.
+
+ If no threads are available at the time of calling, then this function
+ does nothing and returns false. Otherwise, \a runnable is run immediately
+ using one available thread and this function returns true.
+
+ Note that the thread pool takes ownership of the \a runnable if
+ \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns true,
+ and the \a runnable will be deleted automatically by the thread
+ pool after the \l{QRunnable::run()}{runnable->run()} returns. If
+ \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns false,
+ ownership of \a runnable remains with the caller. Note that
+ changing the auto-deletion on \a runnable after calling this
+ function results in undefined behavior.
+*/
+bool QThreadPool::tryStart(QRunnable *runnable)
+{
+ if (!runnable)
+ return false;
+
+ Q_D(QThreadPool);
+
+ // To improve scalability perform a check on the thread count
+ // before locking the mutex.
+ if (d->allThreads.isEmpty() == false && d->activeThreadCount() >= d->maxThreadCount)
+ return false;
+
+ QMutexLocker locker(&d->mutex);
+ return d->tryStart(runnable);
+}
+
+/*! \property QThreadPool::expiryTimeout
+
+ Threads that are unused for \a expiryTimeout milliseconds are considered
+ to have expired and will exit. Such threads will be restarted as needed.
+ The default \a expiryTimeout is 30000 milliseconds (30 seconds). If
+ \a expiryTimeout is negative, newly created threads will not expire, e.g.,
+ they will not exit until the thread pool is destroyed.
+
+ Note that setting \a expiryTimeout has no effect on already running
+ threads. Only newly created threads will use the new \a expiryTimeout.
+ We recommend setting the \a expiryTimeout immediately after creating the
+ thread pool, but before calling start().
+*/
+
+int QThreadPool::expiryTimeout() const
+{
+ Q_D(const QThreadPool);
+ return d->expiryTimeout;
+}
+
+void QThreadPool::setExpiryTimeout(int expiryTimeout)
+{
+ Q_D(QThreadPool);
+ if (d->expiryTimeout == expiryTimeout)
+ return;
+ d->expiryTimeout = expiryTimeout;
+}
+
+/*! \property QThreadPool::maxThreadCount
+
+ This property represents the maximum number of threads used by the thread
+ pool.
+
+ \note The thread pool will always use at least 1 thread, even if
+ \a maxThreadCount limit is zero or negative.
+
+ The default \a maxThreadCount is QThread::idealThreadCount().
+*/
+
+int QThreadPool::maxThreadCount() const
+{
+ Q_D(const QThreadPool);
+ return d->maxThreadCount;
+}
+
+void QThreadPool::setMaxThreadCount(int maxThreadCount)
+{
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+
+ if (maxThreadCount == d->maxThreadCount)
+ return;
+
+ d->maxThreadCount = maxThreadCount;
+ d->tryToStartMoreThreads();
+}
+
+/*! \property QThreadPool::activeThreadCount
+
+ This property represents the number of active threads in the thread pool.
+
+ \note It is possible for this function to return a value that is greater
+ than maxThreadCount(). See reserveThread() for more details.
+
+ \sa reserveThread(), releaseThread()
+*/
+
+int QThreadPool::activeThreadCount() const
+{
+ Q_D(const QThreadPool);
+ return d->activeThreadCount();
+}
+
+/*!
+ Reserves one thread, disregarding activeThreadCount() and maxThreadCount().
+
+ Once you are done with the thread, call releaseThread() to allow it to be
+ reused.
+
+ \note This function will always increase the number of active threads.
+ This means that by using this function, it is possible for
+ activeThreadCount() to return a value greater than maxThreadCount() .
+
+ \sa releaseThread()
+ */
+void QThreadPool::reserveThread()
+{
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ ++d->reservedThreads;
+}
+
+/*!
+ Releases a thread previously reserved by a call to reserveThread().
+
+ \note Calling this function without previously reserving a thread
+ temporarily increases maxThreadCount(). This is useful when a
+ thread goes to sleep waiting for more work, allowing other threads
+ to continue. Be sure to call reserveThread() when done waiting, so
+ that the thread pool can correctly maintain the
+ activeThreadCount().
+
+ \sa reserveThread()
+*/
+void QThreadPool::releaseThread()
+{
+ Q_D(QThreadPool);
+ QMutexLocker locker(&d->mutex);
+ --d->reservedThreads;
+ d->tryToStartMoreThreads();
+}
+
+/*!
+ Waits for each thread to exit and removes all threads from the thread pool.
+*/
+void QThreadPool::waitForDone()
+{
+ Q_D(QThreadPool);
+ d->waitForDone();
+ d->reset();
+}
+
+/*!
+ \overload waitForDone()
+ \since 4.8
+
+ Waits up to \a msecs milliseconds for all threads to exit and removes all
+ threads from the thread pool. Returns true if all threads were removed;
+ otherwise it returns false.
+*/
+bool QThreadPool::waitForDone(int msecs)
+{
+ Q_D(QThreadPool);
+ bool rc = d->waitForDone(msecs);
+ if (rc)
+ d->reset();
+ return rc;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/concurrent/qthreadpool.h b/src/corelib/concurrent/qthreadpool.h
new file mode 100644
index 0000000000..d0326caa8c
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTHREADPOOL_H
+#define QTHREADPOOL_H
+
+#include <QtCore/qglobal.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qrunnable.h>
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QThreadPoolPrivate;
+class Q_CORE_EXPORT QThreadPool : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QThreadPool)
+ Q_PROPERTY(int expiryTimeout READ expiryTimeout WRITE setExpiryTimeout)
+ Q_PROPERTY(int maxThreadCount READ maxThreadCount WRITE setMaxThreadCount)
+ Q_PROPERTY(int activeThreadCount READ activeThreadCount)
+ friend class QFutureInterfaceBase;
+
+public:
+ QThreadPool(QObject *parent = 0);
+ ~QThreadPool();
+
+ static QThreadPool *globalInstance();
+
+ void start(QRunnable *runnable, int priority = 0);
+ bool tryStart(QRunnable *runnable);
+
+ int expiryTimeout() const;
+ void setExpiryTimeout(int expiryTimeout);
+
+ int maxThreadCount() const;
+ void setMaxThreadCount(int maxThreadCount);
+
+ int activeThreadCount() const;
+
+ void reserveThread();
+ void releaseThread();
+
+ void waitForDone();
+ bool waitForDone(int msecs);
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_THREAD
+
+#endif
diff --git a/src/corelib/concurrent/qthreadpool_p.h b/src/corelib/concurrent/qthreadpool_p.h
new file mode 100644
index 0000000000..8f38df7efc
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTHREADPOOL_P_H
+#define QTHREADPOOL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+
+#include "QtCore/qmutex.h"
+#include "QtCore/qwaitcondition.h"
+#include "QtCore/qset.h"
+#include "QtCore/qqueue.h"
+#include "private/qobject_p.h"
+
+#ifndef QT_NO_THREAD
+
+QT_BEGIN_NAMESPACE
+
+class QThreadPoolThread;
+class QThreadPoolPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QThreadPool)
+ friend class QThreadPoolThread;
+
+public:
+ QThreadPoolPrivate();
+
+ bool tryStart(QRunnable *task);
+ void enqueueTask(QRunnable *task, int priority = 0);
+ int activeThreadCount() const;
+
+ void tryToStartMoreThreads();
+ bool tooManyThreadsActive() const;
+
+ void startThread(QRunnable *runnable = 0);
+ void reset();
+ bool waitForDone(int msecs = -1);
+ bool startFrontRunnable();
+ void stealRunnable(QRunnable *);
+
+ mutable QMutex mutex;
+ QWaitCondition runnableReady;
+ QSet<QThreadPoolThread *> allThreads;
+ QQueue<QThreadPoolThread *> expiredThreads;
+ QList<QPair<QRunnable *, int> > queue;
+ QWaitCondition noActiveThreads;
+
+ bool isExiting;
+ int expiryTimeout;
+ int maxThreadCount;
+ int reservedThreads;
+ int waitingThreads;
+ int activeThreads;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_THREAD
+#endif