From 2e27b98cffcd96d4e1d8a0b5836a36dc9929f676 Mon Sep 17 00:00:00 2001 From: Sona Kurazyan Date: Thu, 24 Sep 2020 11:07:32 +0200 Subject: [PATCH] Use universal references in QtConcurrent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed QtConcurrent algorithms to take the passed sequences as universal references, where it makes sense. In addition to avoiding to create extra copies when passing rvalues, this change allows passing temporary container adaptors to QtConcurrent::map (e.g. see the example in the ticket and the new test-cases). Task-number: QTBUG-83170 Change-Id: Ia7c0833f4ec1d860294fa5214cd53934b65ff084 Reviewed-by: Andrei Golubev Reviewed-by: Jarek Kobus Reviewed-by: MÃ¥rten Nordheim --- src/concurrent/qtconcurrentfilter.cpp | 30 ++--- src/concurrent/qtconcurrentfilter.h | 127 ++++++++++-------- src/concurrent/qtconcurrentfilterkernel.h | 36 ++--- src/concurrent/qtconcurrentfunctionwrappers.h | 1 + src/concurrent/qtconcurrentmap.cpp | 38 +++--- src/concurrent/qtconcurrentmap.h | 127 +++++++++--------- src/concurrent/qtconcurrentmapkernel.h | 42 +++--- src/concurrent/qtconcurrentreducekernel.h | 15 +++ .../qtconcurrentmap/tst_qtconcurrentmap.cpp | 53 +++++++- 9 files changed, 281 insertions(+), 188 deletions(-) diff --git a/src/concurrent/qtconcurrentfilter.cpp b/src/concurrent/qtconcurrentfilter.cpp index ce484dcef9d..298e1684fc1 100644 --- a/src/concurrent/qtconcurrentfilter.cpp +++ b/src/concurrent/qtconcurrentfilter.cpp @@ -263,7 +263,7 @@ */ /*! - \fn template QFuture QtConcurrent::filtered(QThreadPool *pool, const Sequence &sequence, KeepFunctor filterFunction) + \fn template QFuture QtConcurrent::filtered(QThreadPool *pool, Sequence &&sequence, KeepFunctor filterFunction) Calls \a filterFunction once for each item in \a sequence and returns a new Sequence of kept items. All calls to \a filterFunction are invoked from the threads @@ -275,7 +275,7 @@ */ /*! - \fn template QFuture QtConcurrent::filtered(const Sequence &sequence, KeepFunctor filterFunction) + \fn template QFuture QtConcurrent::filtered(Sequence &&sequence, KeepFunctor filterFunction) Calls \a filterFunction once for each item in \a sequence and returns a new Sequence of kept items. If \a filterFunction returns \c true, a copy of @@ -309,7 +309,7 @@ */ /*! - \fn template QFuture QtConcurrent::filteredReduced(QThreadPool *pool, const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) + \fn template QFuture QtConcurrent::filteredReduced(QThreadPool *pool, Sequence &&sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) Calls \a filterFunction once for each item in \a sequence. All calls to \a filterFunction are invoked from the threads taken from the QThreadPool \a pool. @@ -328,7 +328,7 @@ */ /*! - \fn template QFuture QtConcurrent::filteredReduced(const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) + \fn template QFuture QtConcurrent::filteredReduced(Sequence &&sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) Calls \a filterFunction once for each item in \a sequence. If \a filterFunction returns \c true for an item, that item is then passed to @@ -346,7 +346,7 @@ */ /*! - \fn template QFuture QtConcurrent::filteredReduced(QThreadPool *pool, const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) + \fn template QFuture QtConcurrent::filteredReduced(QThreadPool *pool, Sequence &&sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) Calls \a filterFunction once for each item in \a sequence. All calls to \a filterFunction are invoked from the threads taken from the QThreadPool \a pool. @@ -368,7 +368,7 @@ */ /*! - \fn template QFuture QtConcurrent::filteredReduced(const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) + \fn template QFuture QtConcurrent::filteredReduced(Sequence &&sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) Calls \a filterFunction once for each item in \a sequence. If \a filterFunction returns \c true for an item, that item is then passed to @@ -500,7 +500,7 @@ */ /*! - \fn template Sequence QtConcurrent::blockingFiltered(QThreadPool *pool, const Sequence &sequence, KeepFunctor filterFunction) + \fn template Sequence QtConcurrent::blockingFiltered(QThreadPool *pool, Sequence &&sequence, KeepFunctor filterFunction) Calls \a filterFunction once for each item in \a sequence and returns a new Sequence of kept items. All calls to \a filterFunction are invoked from the threads @@ -514,7 +514,7 @@ */ /*! - \fn template Sequence QtConcurrent::blockingFiltered(const Sequence &sequence, KeepFunctor filterFunction) + \fn template Sequence QtConcurrent::blockingFiltered(Sequence &&sequence, KeepFunctor filterFunction) Calls \a filterFunction once for each item in \a sequence and returns a new Sequence of kept items. If \a filterFunction returns \c true, a copy of @@ -556,7 +556,7 @@ */ /*! - \fn template ResultType QtConcurrent::blockingFilteredReduced(QThreadPool *pool, const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) + \fn template ResultType QtConcurrent::blockingFilteredReduced(QThreadPool *pool, Sequence &&sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) Calls \a filterFunction once for each item in \a sequence. All calls to \a filterFunction are invoked from the threads taken from the QThreadPool \a pool. @@ -577,7 +577,7 @@ */ /*! - \fn template ResultType QtConcurrent::blockingFilteredReduced(const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) + \fn template ResultType QtConcurrent::blockingFilteredReduced(Sequence &&sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) Calls \a filterFunction once for each item in \a sequence. If \a filterFunction returns \c true for an item, that item is then passed to @@ -597,7 +597,7 @@ */ /*! - \fn template ResultType QtConcurrent::blockingFilteredReduced(QThreadPool *pool, const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) + \fn template ResultType QtConcurrent::blockingFilteredReduced(QThreadPool *pool, Sequence &&sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) Calls \a filterFunction once for each item in \a sequence. All calls to \a filterFunction are invoked from the threads taken from the QThreadPool \a pool. @@ -621,7 +621,7 @@ */ /*! - \fn template ResultType QtConcurrent::blockingFilteredReduced(const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) + \fn template ResultType QtConcurrent::blockingFilteredReduced(Sequence &&sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) Calls \a filterFunction once for each item in \a sequence. If \a filterFunction returns \c true for an item, that item is then passed to @@ -741,12 +741,12 @@ */ /*! - \fn [QtConcurrent-3] ThreadEngineStarter QtConcurrent::startFiltered(QThreadPool *pool, const Sequence &sequence, KeepFunctor functor) + \fn [QtConcurrent-3] ThreadEngineStarter QtConcurrent::startFiltered(QThreadPool *pool, Sequence &&sequence, KeepFunctor functor) \internal */ /*! - \fn [QtConcurrent-4] ThreadEngineStarter QtConcurrent::startFilteredReduced(QThreadPool *pool, const Sequence &sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ReduceOptions options) + \fn [QtConcurrent-4] ThreadEngineStarter QtConcurrent::startFilteredReduced(QThreadPool *pool, Sequence &&sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ReduceOptions options) \internal */ @@ -756,7 +756,7 @@ */ /*! - \fn [QtConcurrent-6] ThreadEngineStarter QtConcurrent::startFilteredReduced(QThreadPool *pool, const Sequence &sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType initialValue, ReduceOptions options) + \fn [QtConcurrent-6] ThreadEngineStarter QtConcurrent::startFilteredReduced(QThreadPool *pool, Sequence &&sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType initialValue, ReduceOptions options) \internal */ diff --git a/src/concurrent/qtconcurrentfilter.h b/src/concurrent/qtconcurrentfilter.h index e383118874a..a85cbc02248 100644 --- a/src/concurrent/qtconcurrentfilter.h +++ b/src/concurrent/qtconcurrentfilter.h @@ -77,78 +77,82 @@ QFuture filter(Sequence &sequence, KeepFunctor keep) // filteredReduced() on sequences template QFuture filteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced(pool, sequence, keep, reduce, options); + return startFilteredReduced(pool, std::forward(sequence), keep, reduce, + options); } template -QFuture filteredReduced(const Sequence &sequence, +QFuture filteredReduced(Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced(QThreadPool::globalInstance(), - sequence, keep, reduce, options); + return startFilteredReduced( + QThreadPool::globalInstance(), std::forward(sequence), keep, reduce, options); } template , int> = 0> QFuture filteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced(pool, sequence, keep, reduce, - ResultType(std::forward(initialValue)), options); + return startFilteredReduced( + pool, std::forward(sequence), keep, reduce, + ResultType(std::forward(initialValue)), options); } template , int> = 0> -QFuture filteredReduced(const Sequence &sequence, +QFuture filteredReduced(Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced(QThreadPool::globalInstance(), sequence, keep, reduce, - ResultType(std::forward(initialValue)), options); + return startFilteredReduced( + QThreadPool::globalInstance(), std::forward(sequence), keep, reduce, + ResultType(std::forward(initialValue)), options); } #ifndef Q_CLANG_QDOC template ::ResultType> QFuture filteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced(pool, sequence, keep, reduce, options); + return startFilteredReduced(pool, std::forward(sequence), keep, reduce, + options); } template ::ResultType> -QFuture filteredReduced(const Sequence &sequence, +QFuture filteredReduced(Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced(QThreadPool::globalInstance(), - sequence, keep, reduce, options); + return startFilteredReduced( + QThreadPool::globalInstance(), std::forward(sequence), keep, reduce, options); } template , int> = 0> QFuture filteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced(pool, sequence, keep, reduce, - ResultType(std::forward(initialValue)), options); + return startFilteredReduced( + pool, std::forward(sequence), keep, reduce, + ResultType(std::forward(initialValue)), options); } template ::ResultType, typename InitialValueType, std::enable_if_t, int> = 0> -QFuture filteredReduced(const Sequence &sequence, +QFuture filteredReduced(Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced(QThreadPool::globalInstance(), sequence, keep, reduce, - ResultType(std::forward(initialValue)), options); + return startFilteredReduced( + QThreadPool::globalInstance(), std::forward(sequence), keep, reduce, + ResultType(std::forward(initialValue)), options); } #endif @@ -302,17 +308,16 @@ QFuture filteredReduced(Iterator begin, // filtered() on sequences template -QFuture filtered(QThreadPool *pool, - const Sequence &sequence, - KeepFunctor keep) +QFuture::value_type> filtered(QThreadPool *pool, + Sequence &&sequence, KeepFunctor keep) { - return startFiltered(pool, sequence, keep); + return startFiltered(pool, std::forward(sequence), keep); } template -QFuture filtered(const Sequence &sequence, KeepFunctor keep) +QFuture::value_type> filtered(Sequence &&sequence, KeepFunctor keep) { - return startFiltered(QThreadPool::globalInstance(), sequence, keep); + return startFiltered(QThreadPool::globalInstance(), std::forward(sequence), keep); } // filtered() on iterators @@ -352,26 +357,26 @@ void blockingFilter(Sequence &sequence, KeepFunctor keep) // blocking filteredReduced() on sequences template ResultType blockingFilteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - QFuture future = startFilteredReduced(pool, sequence, keep, - reduce, options); + QFuture future = startFilteredReduced( + pool, std::forward(sequence), keep, reduce, options); return future.result(); } template -ResultType blockingFilteredReduced(const Sequence &sequence, +ResultType blockingFilteredReduced(Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - QFuture future = startFilteredReduced(QThreadPool::globalInstance(), - sequence, keep, reduce, options); + QFuture future = startFilteredReduced( + QThreadPool::globalInstance(), std::forward(sequence), keep, reduce, options); return future.result(); } @@ -379,30 +384,32 @@ template , int> = 0> ResultType blockingFilteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - QFuture future = startFilteredReduced(pool, sequence, keep, reduce, - ResultType(std::forward(initialValue)), options); + QFuture future = startFilteredReduced( + pool, std::forward(sequence), keep, reduce, + ResultType(std::forward(initialValue)), options); return future.result(); } template , int> = 0> -ResultType blockingFilteredReduced(const Sequence &sequence, +ResultType blockingFilteredReduced(Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - QFuture future = startFilteredReduced(QThreadPool::globalInstance(), - sequence, keep, reduce, ResultType(std::forward(initialValue)), options); + QFuture future = startFilteredReduced( + QThreadPool::globalInstance(), std::forward(sequence), keep, reduce, + ResultType(std::forward(initialValue)), options); return future.result(); } @@ -410,27 +417,27 @@ ResultType blockingFilteredReduced(const Sequence &sequence, template ::ResultType> ResultType blockingFilteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - QFuture future = startFilteredReduced(pool, sequence, keep, - reduce, options); + QFuture future = startFilteredReduced( + pool, std::forward(sequence), keep, reduce, options); return future.result(); } template ::ResultType> -ResultType blockingFilteredReduced(const Sequence &sequence, +ResultType blockingFilteredReduced(Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - QFuture future = startFilteredReduced(QThreadPool::globalInstance(), - sequence, keep, reduce, options); + QFuture future = startFilteredReduced( + QThreadPool::globalInstance(), std::forward(sequence), keep, reduce, options); return future.result(); } @@ -439,15 +446,16 @@ template , int> = 0> ResultType blockingFilteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - QFuture future = startFilteredReduced(pool, sequence, keep, reduce, - ResultType(std::forward(initialValue)), options); + QFuture future = startFilteredReduced( + pool, std::forward(sequence), keep, reduce, + ResultType(std::forward(initialValue)), options); return future.result(); } @@ -455,15 +463,16 @@ template ::ResultType, typename InitialValueType, std::enable_if_t, int> = 0> -ResultType blockingFilteredReduced(const Sequence &sequence, +ResultType blockingFilteredReduced(Sequence &&sequence, KeepFunctor keep, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - QFuture future = startFilteredReduced(QThreadPool::globalInstance(), - sequence, keep, reduce, ResultType(std::forward(initialValue)), options); + QFuture future = startFilteredReduced( + QThreadPool::globalInstance(), std::forward(sequence), keep, reduce, + ResultType(std::forward(initialValue)), options); return future.result(); } #endif @@ -596,17 +605,19 @@ ResultType blockingFilteredReduced(Iterator begin, // blocking filtered() on sequences template -Sequence blockingFiltered(QThreadPool *pool, const Sequence &sequence, KeepFunctor keep) +auto blockingFiltered(QThreadPool *pool, Sequence &&sequence, KeepFunctor keep) { - return blockingFilteredReduced(pool, sequence, keep, QtPrivate::PushBackWrapper(), - OrderedReduce); + return blockingFilteredReduced>( + pool, std::forward(sequence), keep, QtPrivate::PushBackWrapper(), + OrderedReduce); } template -Sequence blockingFiltered(const Sequence &sequence, KeepFunctor keep) +auto blockingFiltered(Sequence &&sequence, KeepFunctor keep) { - return blockingFilteredReduced(QThreadPool::globalInstance(), sequence, keep, - QtPrivate::PushBackWrapper(), OrderedReduce); + return blockingFilteredReduced>( + QThreadPool::globalInstance(), std::forward(sequence), keep, + QtPrivate::PushBackWrapper(), OrderedReduce); } // blocking filtered() on iterators diff --git a/src/concurrent/qtconcurrentfilterkernel.h b/src/concurrent/qtconcurrentfilterkernel.h index 5f9094f6b68..7077327ae44 100644 --- a/src/concurrent/qtconcurrentfilterkernel.h +++ b/src/concurrent/qtconcurrentfilterkernel.h @@ -308,33 +308,35 @@ startFiltered(QThreadPool *pool, Iterator begin, Iterator end, KeepFunctor funct //! [QtConcurrent-3] template -inline ThreadEngineStarter -startFiltered(QThreadPool *pool, const Sequence &sequence, KeepFunctor functor) +inline decltype(auto) startFiltered(QThreadPool *pool, Sequence &&sequence, KeepFunctor functor) { - typedef SequenceHolder1, + using DecayedSequence = std::decay_t; + typedef SequenceHolder1, KeepFunctor> - SequenceHolderType; - return startThreadEngine(new SequenceHolderType(pool, sequence, functor)); + SequenceHolderType; + return startThreadEngine( + new SequenceHolderType(pool, std::forward(sequence), functor)); } //! [QtConcurrent-4] template inline ThreadEngineStarter startFilteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ReduceOptions options) { - typedef typename Sequence::const_iterator Iterator; + using DecayedSequence = std::decay_t; + typedef typename DecayedSequence::const_iterator Iterator; typedef ReduceKernel::value_type > Reducer; typedef FilteredReducedKernel FilteredReduceType; - typedef SequenceHolder2 + typedef SequenceHolder2 SequenceHolderType; - return startThreadEngine(new SequenceHolderType(pool, sequence, mapFunctor, - reduceFunctor, options)); + return startThreadEngine(new SequenceHolderType(pool, std::forward(sequence), + mapFunctor, reduceFunctor, options)); } @@ -359,21 +361,23 @@ inline ThreadEngineStarter startFilteredReduced(QThreadPool *pool, //! [QtConcurrent-6] template inline ThreadEngineStarter startFilteredReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType &&initialValue, ReduceOptions options) { - typedef typename Sequence::const_iterator Iterator; + using DecayedSequence = std::decay_t; + typedef typename DecayedSequence::const_iterator Iterator; typedef ReduceKernel::value_type > Reducer; typedef FilteredReducedKernel FilteredReduceType; - typedef SequenceHolder2 + typedef SequenceHolder2 SequenceHolderType; - return startThreadEngine(new SequenceHolderType(pool, sequence, mapFunctor, reduceFunctor, - std::forward(initialValue), options)); + return startThreadEngine( + new SequenceHolderType(pool, std::forward(sequence), mapFunctor, + reduceFunctor, std::forward(initialValue), options)); } //! [QtConcurrent-7] diff --git a/src/concurrent/qtconcurrentfunctionwrappers.h b/src/concurrent/qtconcurrentfunctionwrappers.h index b66f9c14b48..bb78ea99537 100644 --- a/src/concurrent/qtconcurrentfunctionwrappers.h +++ b/src/concurrent/qtconcurrentfunctionwrappers.h @@ -168,6 +168,7 @@ template struct SequenceHolder { SequenceHolder(const Sequence &s) : sequence(s) { } + SequenceHolder(Sequence &&s) : sequence(std::move(s)) { } Sequence sequence; }; diff --git a/src/concurrent/qtconcurrentmap.cpp b/src/concurrent/qtconcurrentmap.cpp index 43763a441fd..43313feeef3 100644 --- a/src/concurrent/qtconcurrentmap.cpp +++ b/src/concurrent/qtconcurrentmap.cpp @@ -104,12 +104,12 @@ */ /*! - \fn [qtconcurrentmapkernel-3] ThreadEngineStarter QtConcurrent::startMapped(const Sequence &sequence, Functor functor) + \fn [qtconcurrentmapkernel-3] ThreadEngineStarter QtConcurrent::startMapped(Sequence &&sequence, Functor functor) \internal */ /*! - \fn [qtconcurrentmapkernel-4] ThreadEngineStarter QtConcurrent::startMappedReduced(const Sequence & sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ReduceOptions options) + \fn [qtconcurrentmapkernel-4] ThreadEngineStarter QtConcurrent::startMappedReduced(Sequence && sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ReduceOptions options) \internal */ @@ -119,7 +119,7 @@ */ /*! - \fn [qtconcurrentmapkernel-6] ThreadEngineStarter QtConcurrent::startMappedReduced(const Sequence & sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType &&initialValue, ReduceOptions options) + \fn [qtconcurrentmapkernel-6] ThreadEngineStarter QtConcurrent::startMappedReduced(Sequence && sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType &&initialValue, ReduceOptions options) \internal */ @@ -320,7 +320,7 @@ */ /*! - \fn template QFuture QtConcurrent::map(QThreadPool *pool, Sequence &sequence, MapFunctor function) + \fn template QFuture QtConcurrent::map(QThreadPool *pool, Sequence &&sequence, MapFunctor function) Calls \a function once for each item in \a sequence. All calls to \a function are invoked from the threads taken from the QThreadPool \a pool. @@ -331,7 +331,7 @@ */ /*! - \fn template QFuture QtConcurrent::map(Sequence &sequence, MapFunctor function) + \fn template QFuture QtConcurrent::map(Sequence &&sequence, MapFunctor function) Calls \a function once for each item in \a sequence. The \a function takes a reference to the item, so that any modifications done to the item @@ -362,7 +362,7 @@ */ /*! - \fn template QFuture> QtConcurrent::mapped(QThreadPool *pool, const Sequence &sequence, MapFunctor function) + \fn template QFuture> QtConcurrent::mapped(QThreadPool *pool, Sequence &&sequence, MapFunctor function) Calls \a function once for each item in \a sequence and returns a future with each mapped item as a result. All calls to \a function are invoked from the @@ -373,7 +373,7 @@ */ /*! - \fn template QFuture> QtConcurrent::mapped(const Sequence &sequence, MapFunctor function) + \fn template QFuture> QtConcurrent::mapped(Sequence &&sequence, MapFunctor function) 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 @@ -404,7 +404,7 @@ */ /*! - \fn template QFuture QtConcurrent::mappedReduced(QThreadPool *pool, const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) + \fn template QFuture QtConcurrent::mappedReduced(QThreadPool *pool, Sequence &&sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) Calls \a mapFunction once for each item in \a sequence. All calls to \a mapFunction are invoked from the threads taken from the QThreadPool \a pool. @@ -418,7 +418,7 @@ */ /*! - \fn template QFuture QtConcurrent::mappedReduced(const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) + \fn template QFuture QtConcurrent::mappedReduced(Sequence &&sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) Calls \a mapFunction once for each item in \a sequence. The return value of each \a mapFunction is passed to \a reduceFunction. @@ -431,7 +431,7 @@ */ /*! - \fn template QFuture QtConcurrent::mappedReduced(QThreadPool *pool, const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) + \fn template QFuture QtConcurrent::mappedReduced(QThreadPool *pool, Sequence &&sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) Calls \a mapFunction once for each item in \a sequence. All calls to \a mapFunction are invoked from the threads taken from the QThreadPool \a pool. @@ -448,7 +448,7 @@ */ /*! - \fn template QFuture QtConcurrent::mappedReduced(const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) + \fn template QFuture QtConcurrent::mappedReduced(Sequence &&sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) Calls \a mapFunction once for each item in \a sequence. The return value of each \a mapFunction is passed to \a reduceFunction. @@ -532,7 +532,7 @@ */ /*! - \fn template void QtConcurrent::blockingMap(QThreadPool *pool, Sequence &sequence, MapFunctor function) + \fn template void QtConcurrent::blockingMap(QThreadPool *pool, Sequence &&sequence, MapFunctor function) Calls \a function once for each item in \a sequence. All calls to \a function are invoked from the threads taken from the QThreadPool \a pool. @@ -545,7 +545,7 @@ */ /*! - \fn template void QtConcurrent::blockingMap(Sequence &sequence, MapFunctor function) + \fn template void QtConcurrent::blockingMap(Sequence &&sequence, MapFunctor function) Calls \a function once for each item in \a sequence. The \a function takes a reference to the item, so that any modifications done to the item @@ -584,7 +584,7 @@ */ /*! - \fn template OutputSequence QtConcurrent::blockingMapped(QThreadPool *pool, const InputSequence &sequence, MapFunctor function) + \fn template OutputSequence QtConcurrent::blockingMapped(QThreadPool *pool, InputSequence &&sequence, MapFunctor function) Calls \a function once for each item in \a sequence and returns an OutputSequence containing the results. All calls to \a function are invoked from the threads taken from the QThreadPool @@ -596,7 +596,7 @@ */ /*! - \fn template OutputSequence QtConcurrent::blockingMapped(const InputSequence &sequence, MapFunctor function) + \fn template OutputSequence QtConcurrent::blockingMapped(const InputSequence &&sequence, MapFunctor function) Calls \a function once for each item in \a sequence and returns an OutputSequence containing the results. The type of the results will match the type returned my the MapFunctor. @@ -642,7 +642,7 @@ */ /*! - \fn template ResultType QtConcurrent::blockingMappedReduced(QThreadPool *pool, const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) + \fn template ResultType QtConcurrent::blockingMappedReduced(QThreadPool *pool, Sequence &&sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) Calls \a mapFunction once for each item in \a sequence. All calls to \a mapFunction are invoked from the threads taken from the QThreadPool \a pool. @@ -658,7 +658,7 @@ */ /*! - \fn template ResultType QtConcurrent::blockingMappedReduced(const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) + \fn template ResultType QtConcurrent::blockingMappedReduced(Sequence &&sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions) Calls \a mapFunction once for each item in \a sequence. The return value of each \a mapFunction is passed to \a reduceFunction. @@ -673,7 +673,7 @@ */ /*! - \fn template ResultType QtConcurrent::blockingMappedReduced(QThreadPool *pool, const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) + \fn template ResultType QtConcurrent::blockingMappedReduced(QThreadPool *pool, Sequence &&sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) Calls \a mapFunction once for each item in \a sequence. All calls to \a mapFunction are invoked from the threads taken from the QThreadPool \a pool. @@ -692,7 +692,7 @@ */ /*! - \fn template ResultType QtConcurrent::blockingMappedReduced(const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) + \fn template ResultType QtConcurrent::blockingMappedReduced(Sequence &&sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions) Calls \a mapFunction once for each item in \a sequence. The return value of each \a mapFunction is passed to \a reduceFunction. diff --git a/src/concurrent/qtconcurrentmap.h b/src/concurrent/qtconcurrentmap.h index e217c9af3a5..e7c188fb8c1 100644 --- a/src/concurrent/qtconcurrentmap.h +++ b/src/concurrent/qtconcurrentmap.h @@ -57,13 +57,13 @@ namespace QtConcurrent { // map() on sequences template -QFuture map(QThreadPool *pool, Sequence &sequence, MapFunctor map) +QFuture map(QThreadPool *pool, Sequence &&sequence, MapFunctor map) { return startMap(pool, sequence.begin(), sequence.end(), map); } template -QFuture map(Sequence &sequence, MapFunctor map) +QFuture map(Sequence &&sequence, MapFunctor map) { return startMap(QThreadPool::globalInstance(), sequence.begin(), sequence.end(), map); } @@ -84,47 +84,47 @@ QFuture map(Iterator begin, Iterator end, MapFunctor map) // mappedReduced() for sequences. template QFuture mappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { return startMappedReduced, ResultType> - (pool, sequence, map, reduce, options); + (pool, std::forward(sequence), map, reduce, options); } template -QFuture mappedReduced(const Sequence &sequence, +QFuture mappedReduced(Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { return startMappedReduced, ResultType> - (QThreadPool::globalInstance(), sequence, map, reduce, options); + (QThreadPool::globalInstance(), std::forward(sequence), map, reduce, options); } template , int> = 0> QFuture mappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced, ResultType> - (pool, sequence, map, reduce, ResultType(std::forward(initialValue)), - options); + return startMappedReduced, ResultType>( + pool, std::forward(sequence), map, reduce, + ResultType(std::forward(initialValue)), options); } template , int> = 0> -QFuture mappedReduced(const Sequence &sequence, +QFuture mappedReduced(Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, InitialValueType &&initialValue, @@ -132,34 +132,34 @@ QFuture mappedReduced(const Sequence &sequence, | SequentialReduce)) { return startMappedReduced, ResultType> - (QThreadPool::globalInstance(), sequence, map, reduce, + (QThreadPool::globalInstance(), std::forward(sequence), map, reduce, ResultType(std::forward(initialValue)), options); } template ::ResultType> QFuture mappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { return startMappedReduced, ResultType> - (pool, sequence, map, reduce, options); + (pool, std::forward(sequence), map, reduce, options); } template ::ResultType> QFuture mappedReduced( - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { return startMappedReduced, ResultType> - (QThreadPool::globalInstance(), sequence, map, reduce, options); + (QThreadPool::globalInstance(), std::forward(sequence), map, reduce, options); } template , int> = 0> QFuture mappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced, ResultType> - (pool, sequence, map, reduce, ResultType(std::forward(initialValue)), - options); + return startMappedReduced, ResultType>( + pool, std::forward(sequence), map, reduce, + ResultType(std::forward(initialValue)), options); } template ::ResultType, typename InitialValueType, std::enable_if_t, int> = 0> -QFuture mappedReduced(const Sequence &sequence, +QFuture mappedReduced(Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, InitialValueType &&initialValue, @@ -191,7 +191,7 @@ QFuture mappedReduced(const Sequence &sequence, | SequentialReduce)) { return startMappedReduced, ResultType> - (QThreadPool::globalInstance(), sequence, map, reduce, + (QThreadPool::globalInstance(), std::forward(sequence), map, reduce, ResultType(std::forward(initialValue)), options); } @@ -320,19 +320,20 @@ QFuture mappedReduced(Iterator begin, template QFuture> mapped( QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map) { - return startMapped>(pool, sequence, map); + return startMapped>( + pool, std::forward(sequence), map); } template QFuture> mapped( - const Sequence &sequence, + Sequence &&sequence, MapFunctor map) { return startMapped> - (QThreadPool::globalInstance(), sequence, map); + (QThreadPool::globalInstance(), std::forward(sequence), map); } // mapped() for iterator ranges. @@ -358,14 +359,14 @@ QFuture> mapped( // blockingMap() for sequences template -void blockingMap(QThreadPool *pool, Sequence &sequence, MapFunctor map) +void blockingMap(QThreadPool *pool, Sequence &&sequence, MapFunctor map) { QFuture future = startMap(pool, sequence.begin(), sequence.end(), map); future.waitForFinished(); } template -void blockingMap(Sequence &sequence, MapFunctor map) +void blockingMap(Sequence &&sequence, MapFunctor map) { QFuture future = startMap(QThreadPool::globalInstance(), sequence.begin(), sequence.end(), map); future.waitForFinished(); @@ -389,7 +390,7 @@ void blockingMap(Iterator begin, Iterator end, MapFunctor map) // blockingMappedReduced() for sequences template ResultType blockingMappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce @@ -397,12 +398,12 @@ ResultType blockingMappedReduced(QThreadPool *pool, { QFuture future = QtConcurrent::startMappedReduced , ResultType> - (pool, sequence, map, reduce, options); + (pool, std::forward(sequence), map, reduce, options); return future.result(); } template -ResultType blockingMappedReduced(const Sequence &sequence, +ResultType blockingMappedReduced(Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce @@ -410,7 +411,7 @@ ResultType blockingMappedReduced(const Sequence &sequence, { QFuture future = QtConcurrent::startMappedReduced , ResultType> - (QThreadPool::globalInstance(), sequence, map, reduce, options); + (QThreadPool::globalInstance(), std::forward(sequence), map, reduce, options); return future.result(); } @@ -418,7 +419,7 @@ template , int> = 0> ResultType blockingMappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, InitialValueType &&initialValue, @@ -426,16 +427,16 @@ ResultType blockingMappedReduced(QThreadPool *pool, | SequentialReduce)) { QFuture future = QtConcurrent::startMappedReduced - , ResultType> - (pool, sequence, map, reduce, ResultType(std::forward(initialValue)), - options); + , ResultType> + (pool, std::forward(sequence), map, reduce, + ResultType(std::forward(initialValue)), options); return future.result(); } template , int> = 0> -ResultType blockingMappedReduced(const Sequence &sequence, +ResultType blockingMappedReduced(Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, InitialValueType &&initialValue, @@ -444,7 +445,7 @@ ResultType blockingMappedReduced(const Sequence &sequence, { QFuture future = QtConcurrent::startMappedReduced , ResultType> - (QThreadPool::globalInstance(), sequence, map, reduce, + (QThreadPool::globalInstance(), std::forward(sequence), map, reduce, ResultType(std::forward(initialValue)), options); return future.result(); } @@ -452,7 +453,7 @@ ResultType blockingMappedReduced(const Sequence &sequence, template ::ResultType> ResultType blockingMappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce @@ -460,13 +461,13 @@ ResultType blockingMappedReduced(QThreadPool *pool, { QFuture future = QtConcurrent::startMappedReduced , ResultType> - (pool, sequence, map, reduce, options); + (pool, std::forward(sequence), map, reduce, options); return future.result(); } template ::ResultType> -ResultType blockingMappedReduced(const Sequence &sequence, +ResultType blockingMappedReduced(Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce @@ -474,7 +475,7 @@ ResultType blockingMappedReduced(const Sequence &sequence, { QFuture future = QtConcurrent::startMappedReduced , ResultType> - (QThreadPool::globalInstance(), sequence, map, reduce, options); + (QThreadPool::globalInstance(), std::forward(sequence), map, reduce, options); return future.result(); } @@ -483,7 +484,7 @@ template , int> = 0> ResultType blockingMappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, InitialValueType &&initialValue, @@ -492,8 +493,8 @@ ResultType blockingMappedReduced(QThreadPool *pool, { QFuture future = QtConcurrent::startMappedReduced , ResultType> - (pool, sequence, map, reduce, ResultType(std::forward(initialValue)), - options); + (pool, std::forward(sequence), map, reduce, + ResultType(std::forward(initialValue)), options); return future.result(); } @@ -501,7 +502,7 @@ template ::ResultType, typename InitialValueType, std::enable_if_t, int> = 0> -ResultType blockingMappedReduced(const Sequence &sequence, +ResultType blockingMappedReduced(Sequence &&sequence, MapFunctor map, ReduceFunctor reduce, InitialValueType &&initialValue, @@ -510,7 +511,7 @@ ResultType blockingMappedReduced(const Sequence &sequence, { QFuture future = QtConcurrent::startMappedReduced , ResultType> - (QThreadPool::globalInstance(), sequence, map, reduce, + (QThreadPool::globalInstance(), std::forward(sequence), map, reduce, ResultType(std::forward(initialValue)), options); return future.result(); } @@ -654,35 +655,37 @@ ResultType blockingMappedReduced(Iterator begin, // mapped() for sequences with a different putput sequence type. template -OutputSequence blockingMapped(QThreadPool *pool, const InputSequence &sequence, MapFunctor map) +OutputSequence blockingMapped(QThreadPool *pool, InputSequence &&sequence, MapFunctor map) { - return blockingMappedReduced(pool, sequence, map, + return blockingMappedReduced(pool, std::forward(sequence), map, QtPrivate::PushBackWrapper(), OrderedReduce); } template -OutputSequence blockingMapped(const InputSequence &sequence, MapFunctor map) +OutputSequence blockingMapped(InputSequence &&sequence, MapFunctor map) { - return blockingMappedReduced(QThreadPool::globalInstance(), sequence, map, - QtPrivate::PushBackWrapper(), OrderedReduce); + return blockingMappedReduced(QThreadPool::globalInstance(), + std::forward(sequence), map, + QtPrivate::PushBackWrapper(), OrderedReduce); } template -auto blockingMapped(QThreadPool *pool, const InputSequence &sequence, MapFunctor map) +auto blockingMapped(QThreadPool *pool, InputSequence &&sequence, MapFunctor map) { - using OutputSequence = typename QtPrivate::MapSequenceResultType::ResultType; - return blockingMappedReduced(pool, sequence, map, QtPrivate::PushBackWrapper(), - OrderedReduce); + using OutputSequence = typename QtPrivate::MapSequenceResultType, + MapFunctor>::ResultType; + return blockingMappedReduced(pool, std::forward(sequence), map, + QtPrivate::PushBackWrapper(), OrderedReduce); } template -auto blockingMapped(const InputSequence &sequence, MapFunctor map) +auto blockingMapped(InputSequence &&sequence, MapFunctor map) { - using OutputSequence = typename QtPrivate::MapSequenceResultType::ResultType; - return blockingMappedReduced(QThreadPool::globalInstance(), sequence, map, - QtPrivate::PushBackWrapper(), OrderedReduce); + using OutputSequence = typename QtPrivate::MapSequenceResultType, + MapFunctor>::ResultType; + return blockingMappedReduced(QThreadPool::globalInstance(), + std::forward(sequence), map, + QtPrivate::PushBackWrapper(), OrderedReduce); } // mapped() for iterator ranges diff --git a/src/concurrent/qtconcurrentmapkernel.h b/src/concurrent/qtconcurrentmapkernel.h index 0e6cfa4b9a4..3acf2997525 100644 --- a/src/concurrent/qtconcurrentmapkernel.h +++ b/src/concurrent/qtconcurrentmapkernel.h @@ -221,6 +221,11 @@ inline ThreadEngineStarter startMapped(QThreadPool *pool, Iterator begin, template struct SequenceHolder1 : private QtPrivate::SequenceHolder, public Base { + SequenceHolder1(QThreadPool *pool, Sequence &&_sequence, Functor functor) + : QtPrivate::SequenceHolder(std::move(_sequence)), + Base(pool, this->sequence.cbegin(), this->sequence.cend(), functor) + { } + SequenceHolder1(QThreadPool *pool, const Sequence &_sequence, Functor functor) : QtPrivate::SequenceHolder(_sequence), Base(pool, this->sequence.cbegin(), this->sequence.cend(), functor) @@ -237,33 +242,37 @@ struct SequenceHolder1 : private QtPrivate::SequenceHolder, public Bas //! [qtconcurrentmapkernel-3] template -inline ThreadEngineStarter startMapped(QThreadPool *pool, const Sequence &sequence, +inline ThreadEngineStarter startMapped(QThreadPool *pool, Sequence &&sequence, Functor functor) { - typedef SequenceHolder1, Functor> - SequenceHolderType; + using DecayedSequence = std::decay_t; + typedef SequenceHolder1, + Functor> + SequenceHolderType; - return startThreadEngine(new SequenceHolderType(pool, sequence, functor)); + return startThreadEngine( + new SequenceHolderType(pool, std::forward(sequence), functor)); } //! [qtconcurrentmapkernel-4] template inline ThreadEngineStarter startMappedReduced(QThreadPool *pool, - const Sequence & sequence, + Sequence &&sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ReduceOptions options) { - typedef typename Sequence::const_iterator Iterator; + using DecayedSequence = std::decay_t; + typedef typename DecayedSequence::const_iterator Iterator; typedef ReduceKernel Reducer; typedef MappedReducedKernel MappedReduceType; - typedef SequenceHolder2 + typedef SequenceHolder2 SequenceHolderType; - return startThreadEngine(new SequenceHolderType(pool, sequence, mapFunctor, reduceFunctor, - options)); + return startThreadEngine(new SequenceHolderType(pool, std::forward(sequence), + mapFunctor, reduceFunctor, options)); } //! [qtconcurrentmapkernel-5] @@ -287,21 +296,22 @@ inline ThreadEngineStarter startMappedReduced(QThreadPool *pool, template inline ThreadEngineStarter startMappedReduced(QThreadPool *pool, - const Sequence &sequence, + Sequence &&sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType &&initialValue, ReduceOptions options) { - typedef typename Sequence::const_iterator Iterator; + using DecayedSequence = std::decay_t; + typedef typename DecayedSequence::const_iterator Iterator; typedef ReduceKernel Reducer; typedef MappedReducedKernel MappedReduceType; - typedef SequenceHolder2 + typedef SequenceHolder2 SequenceHolderType; - return startThreadEngine(new SequenceHolderType( - pool, sequence, mapFunctor, reduceFunctor, std::forward(initialValue), - options)); + return startThreadEngine( + new SequenceHolderType(pool, std::forward(sequence), mapFunctor, + reduceFunctor, std::forward(initialValue), options)); } //! [qtconcurrentmapkernel-7] diff --git a/src/concurrent/qtconcurrentreducekernel.h b/src/concurrent/qtconcurrentreducekernel.h index 333d358f189..cdddfdde0d0 100644 --- a/src/concurrent/qtconcurrentreducekernel.h +++ b/src/concurrent/qtconcurrentreducekernel.h @@ -232,6 +232,13 @@ struct SequenceHolder2 : private QtPrivate::SequenceHolder, public Bas reduceOptions) { } + SequenceHolder2(QThreadPool *pool, Sequence &&_sequence, Functor1 functor1, Functor2 functor2, + ReduceOptions reduceOptions) + : QtPrivate::SequenceHolder(std::move(_sequence)), + Base(pool, this->sequence.cbegin(), this->sequence.cend(), functor1, functor2, + reduceOptions) + { } + template SequenceHolder2(QThreadPool *pool, const Sequence &_sequence, Functor1 functor1, Functor2 functor2, InitialValueType &&initialValue, ReduceOptions reduceOptions) @@ -240,6 +247,14 @@ struct SequenceHolder2 : private QtPrivate::SequenceHolder, public Bas std::forward(initialValue), reduceOptions) { } + template + SequenceHolder2(QThreadPool *pool, Sequence &&_sequence, Functor1 functor1, Functor2 functor2, + InitialValueType &&initialValue, ReduceOptions reduceOptions) + : QtPrivate::SequenceHolder(std::move(_sequence)), + Base(pool, this->sequence.cbegin(), this->sequence.cend(), functor1, functor2, + std::forward(initialValue), reduceOptions) + { } + void finish() override { Base::finish(); diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp index 33ec2514521..6b844fa73d5 100644 --- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp +++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp @@ -41,7 +41,8 @@ class tst_QtConcurrentMap : public QObject Q_OBJECT private slots: void map(); - void blocking_map(); + void blockingMap(); + void mapOnRvalue(); void mapped(); void mappedThreadPool(); void mappedReduced(); @@ -211,7 +212,7 @@ void tst_QtConcurrentMap::map() #endif } -void tst_QtConcurrentMap::blocking_map() +void tst_QtConcurrentMap::blockingMap() { // functors take arguments by reference, modifying the sequence in place { @@ -323,6 +324,54 @@ void tst_QtConcurrentMap::blocking_map() #endif } +void tst_QtConcurrentMap::mapOnRvalue() +{ + struct ListRange + { + using iterator = QList::iterator; + ListRange(iterator b, iterator e) : m_begin(b), m_end(e) { } + + iterator begin() const { return m_begin; } + iterator end() const { return m_end; } + + private: + iterator m_begin; + iterator m_end; + }; + + const QList expected { 1, 4, 6, 4 }; + { + QList list { 1, 2, 3, 4 }; + auto future = + QtConcurrent::map(ListRange(list.begin() + 1, list.end() - 1), multiplyBy2InPlace); + future.waitForFinished(); + QCOMPARE(list, expected); + } + + { + QList list { 1, 2, 3, 4 }; + QThreadPool pool; + auto future = QtConcurrent::map(&pool, ListRange(list.begin() + 1, list.end() - 1), + multiplyBy2InPlace); + future.waitForFinished(); + QCOMPARE(list, expected); + } + + { + QList list { 1, 2, 3, 4 }; + QtConcurrent::blockingMap(ListRange(list.begin() + 1, list.end() - 1), multiplyBy2InPlace); + QCOMPARE(list, expected); + } + + { + QList list { 1, 2, 3, 4 }; + QThreadPool pool; + QtConcurrent::blockingMap(&pool, ListRange(list.begin() + 1, list.end() - 1), + multiplyBy2InPlace); + QCOMPARE(list, expected); + } +} + int multiplyBy2(int x) { int y = x * 2;