summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@qt.io>2017-12-11 21:12:10 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-05-13 10:41:25 +0200
commit6faa4d4a87662a6254542da37b3a6fff528e0a6c (patch)
tree04578d13b1c923a3a34e4f9ace27d2884759d76a /src/corelib/thread
parent486c55d7437c247472e287f0f2ccc883399d9f79 (diff)
QFuture: Wait for result on iterator advance
Wait for the result at the target index if the future is running and the iterator index is past the current result count. Determine if there is a result at the target index after waitForResult() returns, and return -1/end if not. Also support decrementing the end iterator. In this case wait for the future to finish in order to get the final result count. Task-number: QTBUG-59811 Change-Id: I8fcc711bab2e72c3c5196a55b794d25e18bb324d Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qfuture.h82
1 files changed, 64 insertions, 18 deletions
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h
index a456dd9139..d3135510b3 100644
--- a/src/corelib/thread/qfuture.h
+++ b/src/corelib/thread/qfuture.h
@@ -111,33 +111,79 @@ public:
typedef const T &reference;
inline const_iterator() {}
- inline const_iterator(QFuture const * const _future, int _index) : future(_future), index(_index) {}
+ inline const_iterator(QFuture const * const _future, int _index)
+ : future(_future), index(advanceIndex(_index, 0)) { }
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
+ inline bool operator!=(const const_iterator &other) const { return index != other.index; }
+ inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
+ inline const_iterator &operator++()
+ { index = advanceIndex(index, 1); return *this; }
+ inline const_iterator &operator--()
+ { index = advanceIndex(index, -1); return *this; }
+ inline const_iterator operator++(int)
+ {
+ const_iterator r = *this;
+ index = advanceIndex(index, 1);
+ return r;
+ }
+ inline const_iterator operator--(int)
{
- 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);
+ const_iterator r = *this;
+ index = advanceIndex(index, -1);
+ return r;
}
+ inline const_iterator operator+(int j) const
+ { return const_iterator(future, advanceIndex(index, j)); }
+ inline const_iterator operator-(int j) const
+ { return const_iterator(future, advanceIndex(index, -j)); }
+ inline const_iterator &operator+=(int j)
+ { index = advanceIndex(index, j); return *this; }
+ inline const_iterator &operator-=(int j)
+ { index = advanceIndex(index, -j); return *this; }
+ friend inline const_iterator operator+(int j, const_iterator k)
+ { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
- 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; }
- friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
private:
+ /*! \internal
+
+ Advances the iterator index \a idx \a n steps, waits for the
+ result at the target index, and returns the target index.
+
+ The index may be -1, indicating the end iterator, either
+ as the argument or as the return value. The end iterator
+ may be decremented.
+
+ The caller is responsible for not advancing the iterator
+ before begin() or past end(), with the exception that
+ attempting to advance a non-end iterator past end() for
+ a running future is allowed and will return the end iterator.
+
+ Note that n == 0 is valid and will wait for the result
+ at the given index.
+ */
+ int advanceIndex(int idx, int n) const
+ {
+ // The end iterator can be decremented, leave as-is for other cases
+ if (idx == -1 && n >= 0)
+ return idx;
+
+ // Special case for decrementing the end iterator: wait for
+ // finished to get the total result count.
+ if (idx == -1 && future->isRunning())
+ future->d.waitForFinished();
+
+ // Wait for result at target index
+ const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
+ future->d.waitForResult(targetIndex);
+
+ // After waiting there is either a result or the end was reached
+ return (targetIndex < future->resultCount()) ? targetIndex : -1;
+ }
+
QFuture const * future;
int index;
};