summaryrefslogtreecommitdiffstats
path: root/src/concurrent
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2020-09-24 10:48:33 +0200
committerSona Kurazyan <sona.kurazyan@qt.io>2020-09-28 15:48:17 +0200
commita6e1f67937c280961f7ec23b2a002ca7d057761d (patch)
tree8ca782fdd8960d035077d112d0caa34ba16e7fa2 /src/concurrent
parentb12d6c6a8ab5f7b01bdd2cb862a66a409700faa1 (diff)
Fix QtConcurrent algorithms to work with temporary sequences
QtConcurrent algorithms are making an internal copy of the passed sequence, to make sure it won't be destroyed before the execution is finished. However, they were using iterators of the originally passed sequence. So, if the original sequence is deleted, QtConcurrent algorithms would use invalid iterators to a deleted sequence. This might work with Qt containers thanks to implicit-sharing, but with other containers will lead to unexpected results. Fixed them to work on the internal copy of the original sequence. Change-Id: I1d68692ed9746223c85f51bb05977bc1443b681d Reviewed-by: Andreas Buhr <andreas.buhr@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
Diffstat (limited to 'src/concurrent')
-rw-r--r--src/concurrent/qtconcurrentfunctionwrappers.h7
-rw-r--r--src/concurrent/qtconcurrentmapkernel.h9
-rw-r--r--src/concurrent/qtconcurrentreducekernel.h35
3 files changed, 25 insertions, 26 deletions
diff --git a/src/concurrent/qtconcurrentfunctionwrappers.h b/src/concurrent/qtconcurrentfunctionwrappers.h
index 34bbe89c86..b66f9c14b4 100644
--- a/src/concurrent/qtconcurrentfunctionwrappers.h
+++ b/src/concurrent/qtconcurrentfunctionwrappers.h
@@ -164,6 +164,13 @@ struct MapSequenceResultType<InputSequence<T>, MapFunctor>
#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
+template<typename Sequence>
+struct SequenceHolder
+{
+ SequenceHolder(const Sequence &s) : sequence(s) { }
+ Sequence sequence;
+};
+
} // namespace QtPrivate.
diff --git a/src/concurrent/qtconcurrentmapkernel.h b/src/concurrent/qtconcurrentmapkernel.h
index 11be262628..0e6cfa4b9a 100644
--- a/src/concurrent/qtconcurrentmapkernel.h
+++ b/src/concurrent/qtconcurrentmapkernel.h
@@ -219,20 +219,19 @@ inline ThreadEngineStarter<T> startMapped(QThreadPool *pool, Iterator begin,
sequence we are working on.
*/
template <typename Sequence, typename Base, typename Functor>
-struct SequenceHolder1 : public Base
+struct SequenceHolder1 : private QtPrivate::SequenceHolder<Sequence>, public Base
{
SequenceHolder1(QThreadPool *pool, const Sequence &_sequence, Functor functor)
- : Base(pool, _sequence.begin(), _sequence.end(), functor), sequence(_sequence)
+ : QtPrivate::SequenceHolder<Sequence>(_sequence),
+ Base(pool, this->sequence.cbegin(), this->sequence.cend(), functor)
{ }
- Sequence sequence;
-
void finish() override
{
Base::finish();
// Clear the sequence to make sure all temporaries are destroyed
// before finished is signaled.
- sequence = Sequence();
+ this->sequence = Sequence();
}
};
diff --git a/src/concurrent/qtconcurrentreducekernel.h b/src/concurrent/qtconcurrentreducekernel.h
index 694ac2b5a9..333d358f18 100644
--- a/src/concurrent/qtconcurrentreducekernel.h
+++ b/src/concurrent/qtconcurrentreducekernel.h
@@ -41,6 +41,7 @@
#define QTCONCURRENT_REDUCEKERNEL_H
#include <QtConcurrent/qtconcurrent_global.h>
+#include <QtConcurrent/qtconcurrentfunctionwrappers.h>
#if !defined(QT_NO_CONCURRENT) || defined(Q_CLANG_QDOC)
@@ -222,37 +223,29 @@ public:
};
template <typename Sequence, typename Base, typename Functor1, typename Functor2>
-struct SequenceHolder2 : public Base
+struct SequenceHolder2 : private QtPrivate::SequenceHolder<Sequence>, public Base
{
- SequenceHolder2(QThreadPool *pool,
- const Sequence &_sequence,
- Functor1 functor1,
- Functor2 functor2,
- ReduceOptions reduceOptions)
- : Base(pool, _sequence.begin(), _sequence.end(), functor1, functor2, reduceOptions),
- sequence(_sequence)
+ SequenceHolder2(QThreadPool *pool, const Sequence &_sequence, Functor1 functor1,
+ Functor2 functor2, ReduceOptions reduceOptions)
+ : QtPrivate::SequenceHolder<Sequence>(_sequence),
+ Base(pool, this->sequence.cbegin(), this->sequence.cend(), functor1, functor2,
+ reduceOptions)
{ }
- template <typename InitialValueType>
- SequenceHolder2(QThreadPool *pool,
- const Sequence &_sequence,
- Functor1 functor1,
- Functor2 functor2,
- InitialValueType &&initialValue,
- ReduceOptions reduceOptions)
- : Base(pool, _sequence.begin(), _sequence.end(), functor1, functor2,
- std::forward<InitialValueType>(initialValue), reduceOptions),
- sequence(_sequence)
+ template<typename InitialValueType>
+ SequenceHolder2(QThreadPool *pool, const Sequence &_sequence, Functor1 functor1,
+ Functor2 functor2, InitialValueType &&initialValue, ReduceOptions reduceOptions)
+ : QtPrivate::SequenceHolder<Sequence>(_sequence),
+ Base(pool, this->sequence.cbegin(), this->sequence.cend(), functor1, functor2,
+ std::forward<InitialValueType>(initialValue), reduceOptions)
{ }
- Sequence sequence;
-
void finish() override
{
Base::finish();
// Clear the sequence to make sure all temporaries are destroyed
// before finished is signaled.
- sequence = Sequence();
+ this->sequence = Sequence();
}
};