summaryrefslogtreecommitdiffstats
path: root/src/corelib/concurrent
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2009-04-24 11:34:15 (GMT)
committeraxis <qt-info@nokia.com>2009-04-24 11:34:15 (GMT)
commit8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch)
treea17e1a767a89542ab59907462206d7dcf2e504b2 /src/corelib/concurrent
downloadQt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip
Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz
Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2
Long live Qt for S60!
Diffstat (limited to 'src/corelib/concurrent')
-rw-r--r--src/corelib/concurrent/concurrent.pri42
-rw-r--r--src/corelib/concurrent/qfuture.cpp695
-rw-r--r--src/corelib/concurrent/qfuture.h278
-rw-r--r--src/corelib/concurrent/qfutureinterface.cpp564
-rw-r--r--src/corelib/concurrent/qfutureinterface.h311
-rw-r--r--src/corelib/concurrent/qfutureinterface_p.h168
-rw-r--r--src/corelib/concurrent/qfuturesynchronizer.cpp154
-rw-r--r--src/corelib/concurrent/qfuturesynchronizer.h121
-rw-r--r--src/corelib/concurrent/qfuturewatcher.cpp574
-rw-r--r--src/corelib/concurrent/qfuturewatcher.h222
-rw-r--r--src/corelib/concurrent/qfuturewatcher_p.h90
-rw-r--r--src/corelib/concurrent/qrunnable.cpp105
-rw-r--r--src/corelib/concurrent/qrunnable.h73
-rw-r--r--src/corelib/concurrent/qtconcurrentcompilertest.h71
-rw-r--r--src/corelib/concurrent/qtconcurrentexception.cpp228
-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.cpp194
-rw-r--r--src/corelib/concurrent/qtconcurrentiteratekernel.h335
-rw-r--r--src/corelib/concurrent/qtconcurrentmap.cpp401
-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.h253
-rw-r--r--src/corelib/concurrent/qtconcurrentresultstore.cpp256
-rw-r--r--src/corelib/concurrent/qtconcurrentresultstore.h239
-rw-r--r--src/corelib/concurrent/qtconcurrentrun.cpp150
-rw-r--r--src/corelib/concurrent/qtconcurrentrun.h297
-rw-r--r--src/corelib/concurrent/qtconcurrentrunbase.h134
-rw-r--r--src/corelib/concurrent/qtconcurrentstoredfunctioncall.h1328
-rw-r--r--src/corelib/concurrent/qtconcurrentthreadengine.cpp219
-rw-r--r--src/corelib/concurrent/qtconcurrentthreadengine.h306
-rw-r--r--src/corelib/concurrent/qthreadpool.cpp614
-rw-r--r--src/corelib/concurrent/qthreadpool.h95
-rw-r--r--src/corelib/concurrent/qthreadpool_p.h107
38 files changed, 11525 insertions, 0 deletions
diff --git a/src/corelib/concurrent/concurrent.pri b/src/corelib/concurrent/concurrent.pri
new file mode 100644
index 0000000..9402971
--- /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 0000000..1840fab
--- /dev/null
+++ b/src/corelib/concurrent/qfuture.cpp
@@ -0,0 +1,695 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class QFuture
+ \threadsafe
+ \brief The QFuture class represents the result of an asynchronous computation.
+ \since 4.4
+
+ To start a computation, use one of the APIs in the
+ \l {threads.html#qtconcurrent-intro}{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, {threads.html#qtconcurrent-intro}{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 0000000..da24db7
--- /dev/null
+++ b/src/corelib/concurrent/qfuture.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 ptrdiff_t 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); }
+
+#ifndef QT_NO_MEMBER_TEMPLATES
+ 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 0000000..b7589b7
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface.cpp
@@ -0,0 +1,564 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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.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), progressTimeStarted(false), pendingResults(0),
+ manualProgress(false), m_expectedResultCount(0), runnable(0)
+{ }
+
+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 (progressTimeStarted == true && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted.
+ if (progressTime.elapsed() < (1000 / MaxProgressEmitsPerSecond))
+ return false;
+
+ progressTime.start();
+ progressTimeStarted = true;
+ 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 0000000..85d03c9
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface.h
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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)
+ {
+ 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 0000000..719d7a1
--- /dev/null
+++ b/src/corelib/concurrent/qfutureinterface_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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/qdatetime.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;
+ QTime progressTime;
+ bool progressTimeStarted;
+ 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 0000000..a0e88f3
--- /dev/null
+++ b/src/corelib/concurrent/qfuturesynchronizer.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class QFutureSynchronizer
+ \since 4.4
+
+ \brief The QFutureSynchronizer class is a convenience class that simplifies
+ QFuture synchronization.
+
+ 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, {threads.html#qtconcurrent-intro}{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 0000000..daf65b9
--- /dev/null
+++ b/src/corelib/concurrent/qfuturesynchronizer.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..ea35e9e
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher.cpp
@@ -0,0 +1,574 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfuturewatcher.h"
+
+#ifndef QT_NO_QFUTURE
+
+#include <QEvent>
+#include <QCoreApplication>
+#include <QThread>
+
+#include "qfuturewatcher_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*! \class QFutureWatcher
+ \reentrant
+ \since 4.4
+
+ \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, {threads.html#qtconcurrent-intro}{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();
+}
+
+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 != QString()) // ###
+ 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.
+*/
+
+/*! \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 0000000..75dfd3d
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher.h
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..324839d
--- /dev/null
+++ b/src/corelib/concurrent/qfuturewatcher_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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>
+
+#ifndef QT_NO_QFUTURE
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFutureWatcherBase;
+class Q_CORE_EXPORT 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 0000000..a581a21
--- /dev/null
+++ b/src/corelib/concurrent/qrunnable.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QRunnable
+ \since 4.4
+ \brief The QRunnable class is the base class for all runnable objects.
+
+ 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 0000000..1f480f4
--- /dev/null
+++ b/src/corelib/concurrent/qrunnable.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..763750a
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentcompilertest.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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)
+
+#ifdef Q_CC_MSVC
+# if _MSC_VER < 1300
+# define QT_CONURRENT_NONSTANDARD_COMPILER
+# endif
+#endif
+
+#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 0000000..cce1c31
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentexception.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 willl 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()
+{
+ /* On win32-g++, with GCC 3.4.2 std::uncaught_exception() isn't reliable. */
+ if (hasException()
+#ifndef Q_CC_MINGW
+ && std::uncaught_exception() == false
+#endif
+ ) {
+ 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 0000000..eaa63d8
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentexception.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..4fbda82
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilter.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtConcurrentFilter>
+ \title Concurrent Filter and Filter-Reduce
+ \ingroup threading
+
+ \brief The <QtConcurrentFilter> header provides concurrent Filter and
+ Filter-Reduce.
+
+ These functions are a part of the \l {threads.html#qtconcurrent-intro}{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 neccesary. 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 0000000..3fae7d2
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilter.h
@@ -0,0 +1,736 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..2ee1246
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfilterkernel.h
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..d076f73
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..5c20146
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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)
+
+#include <time.h>
+#include <unistd.h>
+
+#elif defined(Q_OS_WIN)
+
+#include <windows.h>
+
+#endif
+
+
+#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
+ // no clock_gettime(), fall back to wall time
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return (tv.tv_sec * 1000000) + tv.tv_usec;
+#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 0000000..38d2824
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentiteratekernel.h
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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)
+#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION
+ : begin(_begin), end(_end), current(_begin), currentIndex(0),
+ forIteration(selectIteration(typename std::iterator_traits<Iterator>::iterator_category())), progressReportingEnabled(true)
+#else
+ : begin(_begin), end(_end), currentIndex(0),
+ forIteration(selectIteration(std::iterator_category(_begin))), progressReportingEnabled(true)
+#endif
+ {
+ iterationCount = forIteration ? std::distance(_begin, _end) : 0;
+ }
+
+ 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 0000000..8880a87
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmap.cpp
@@ -0,0 +1,401 @@
+ /****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \namespace QtConcurrent
+ \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 {threads.html#qtconcurrent-intro}{Qt Concurrent} section in the \l{threads.html}{threading} documentation.
+
+ \ingroup thread
+*/
+
+/*!
+ \namespace QtConcurrent::internal
+ \internal
+
+ \brief The QtConcurrent::internal namespace contains QtConcurrent
+ implementation details.
+
+ \ingroup thread
+*/
+
+/*!
+ \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 sequentally: 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 threading
+
+ \brief The <QtConcurrentMap> header provides concurrent Map and MapReduce.
+
+ These functions are a part of the \l {threads.html#qtconcurrent-intro}{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 neccesary. 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 0000000..0d55a74
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmap.h
@@ -0,0 +1,780 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..0c6a5ad
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmapkernel.h
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..a8ad17d
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentmedian.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..e863b63
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentreducekernel.h
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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/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;
+ 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)
+ { }
+
+ 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 * QThread::idealThreadCount()));
+ }
+
+ inline bool shouldStartThread()
+ {
+ return (resultsMapSize <= (ReduceQueueStartLimit * QThread::idealThreadCount()));
+ }
+};
+
+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 0000000..87bb2a7d
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentresultstore.cpp
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 funciton 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 0000000..c39e921
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentresultstore.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..068a913
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrun.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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.
+
+ This function is a part of the \l {threads.html#qtconcurrent-intro}{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 QString::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 0000000..00938fa
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrun.h
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..51f5aa1
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentrunbase.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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;
+ }
+ this->runFunctor();
+ this->reportResult(result);
+ this->reportFinished();
+ }
+ T result;
+};
+
+template <>
+class RunFunctionTask<void> : public RunFunctionTaskBase<void>
+{
+public:
+ void run()
+ {
+ if (this->isCanceled()) {
+ this->reportFinished();
+ return;
+ }
+ this->runFunctor();
+ 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 0000000..c7aeb9d
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentstoredfunctioncall.h
@@ -0,0 +1,1328 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 0000000..d6e6057
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentthreadengine.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtconcurrentthreadengine.h"
+
+#ifndef QT_NO_CONCURRENT
+
+QT_BEGIN_NAMESPACE
+
+namespace QtConcurrent {
+
+ThreadEngineBase::ThreadEngineBase()
+:futureInterface(0), threadPool(QThreadPool::globalInstance())
+{
+ setAutoDelete(false);
+}
+
+ThreadEngineBase::~ThreadEngineBase() {}
+
+void ThreadEngineBase::startSingleThreaded()
+{
+ start();
+ while (threadFunction() != ThreadFinished)
+ ;
+ finish();
+}
+
+void ThreadEngineBase::startBlocking()
+{
+ start();
+ semaphore.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) {
+ semaphore.release();
+ }
+
+ semaphore.wait();
+ finish();
+ exceptionStore.throwPossibleException();
+}
+
+void ThreadEngineBase::startThread()
+{
+ startThreadInternal();
+}
+
+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;
+
+ semaphore.acquire();
+ if (!threadPool->tryStart(this)) {
+ semaphore.release();
+ return false;
+ }
+ return true;
+}
+
+void ThreadEngineBase::startThreads()
+{
+ while (shouldStartThread() && startThreadInternal())
+ ;
+}
+
+void ThreadEngineBase::threadExit()
+{
+ const bool asynchronous = futureInterface != 0;
+ const int lastThread = (semaphore.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 semaphore.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 0000000..9e7d12e
--- /dev/null
+++ b/src/corelib/concurrent/qtconcurrentthreadengine.h
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef qdoc
+
+namespace QtConcurrent {
+
+// A Semaphore that can wait until all resources are returned.
+class ThreadEngineSemaphore
+{
+public:
+ ThreadEngineSemaphore()
+ :count(0) { }
+
+ void acquire()
+ {
+ QMutexLocker lock(&mutex);
+ ++count;
+ }
+
+ int release()
+ {
+ QMutexLocker lock(&mutex);
+ if (--count == 0)
+ waitCondition.wakeAll();
+ return count;
+ }
+
+ // Wait until all resources are released.
+ void wait()
+ {
+ QMutexLocker lock(&mutex);
+ if (count != 0)
+ waitCondition.wait(&mutex);
+ }
+
+ int currentCount()
+ {
+ return count;
+ }
+
+ // releases a resource, unless this is the last resource.
+ // returns true if a resource was released.
+ bool releaseUnlessLast()
+ {
+ QMutexLocker lock(&mutex);
+ if (count == 1)
+ return false;
+ --count;
+ return true;
+ }
+
+private:
+ QMutex mutex;
+ int count;
+ QWaitCondition waitCondition;
+};
+
+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);
+
+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;
+ ThreadEngineSemaphore semaphore;
+ 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();
+
+ semaphore.acquire();
+ 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>
+{
+public:
+ ThreadEngineStarter(ThreadEngine<T> *threadEngine)
+ :ThreadEngineStarterBase<T>(threadEngine) {}
+
+ 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 0000000..30edfd4
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool.cpp
@@ -0,0 +1,614 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qthreadpool.h"
+#include "qthreadpool_p.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
+{
+ 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)
+{
+ QThreadPoolThread *thread = new QThreadPoolThread(this);
+ allThreads.insert(thread);
+ ++activeThreads;
+
+ if (runnable->autoDelete())
+ ++runnable->ref;
+ thread->runnable = runnable;
+ thread->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;
+}
+
+void QThreadPoolPrivate::waitForDone()
+{
+ QMutexLocker locker(&mutex);
+ while (!(queue.isEmpty() && activeThreads == 0))
+ noActiveThreads.wait(locker.mutex());
+}
+
+/*! \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
+
+ 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 {threads.html#qtconcurrent-intro}{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);
+ 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);
+ QMutexLocker locker(&d->mutex);
+ 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);
+ QMutexLocker locker(&d->mutex);
+ 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();
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/concurrent/qthreadpool.h b/src/corelib/concurrent/qthreadpool.h
new file mode 100644
index 0000000..f3dd96c
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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();
+};
+
+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 0000000..6948ee1
--- /dev/null
+++ b/src/corelib/concurrent/qthreadpool_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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();
+ void waitForDone();
+ 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