// 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)); } QtPrivate::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 tst_QFuture::resultStore() { int int0 = 0; int int1 = 1; int int2 = 2; { ResultStoreInt store; QCOMPARE(store.begin(), store.end()); QCOMPARE(store.resultAt(0), store.end()); QCOMPARE(store.resultAt(1), store.end()); } { ResultStoreInt store; store.addResult(-1, &int0); store.addResult(1, &int1); QtPrivate::ResultIteratorBase it = store.begin(); QCOMPARE(it.resultIndex(), 0); QVERIFY(it == store.begin()); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 1); QVERIFY(it != store.begin()); QVERIFY(it != store.end()); ++it; QVERIFY(it != store.begin()); QVERIFY(it == store.end()); } QVector<int> vec0 = QVector<int>() << 2 << 3; QVector<int> vec1 = QVector<int>() << 4 << 5; { ResultStoreInt store; store.addResults(-1, &vec0, 2); store.addResults(-1, &vec1, 2); QtPrivate::ResultIteratorBase it = store.begin(); QCOMPARE(it.resultIndex(), 0); QCOMPARE(it, store.begin()); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 1); QVERIFY(it != store.begin()); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 2); ++it; QCOMPARE(it.resultIndex(), 3); ++it; QCOMPARE(it, store.end()); } { ResultStoreInt store; store.addResult(-1, &int0); store.addResults(-1, &vec1, 2); store.addResult(-1, &int1); QtPrivate::ResultIteratorBase it = store.begin(); QCOMPARE(it.resultIndex(), 0); QVERIFY(it == store.begin()); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 1); QVERIFY(it != store.begin()); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 2); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 3); QVERIFY(it != store.end()); ++it; QVERIFY(it == store.end()); QCOMPARE(store.resultAt(0).resultIndex(), 0); QCOMPARE(store.resultAt(1).resultIndex(), 1); QCOMPARE(store.resultAt(2).resultIndex(), 2); QCOMPARE(store.resultAt(3).resultIndex(), 3); QCOMPARE(store.resultAt(4), store.end()); } { ResultStoreInt store; store.addResult(-1, &int0); store.addResults(-1, &vec0); store.addResult(-1, &int1); QtPrivate::ResultIteratorBase it = store.begin(); QCOMPARE(it.resultIndex(), 0); QVERIFY(it == store.begin()); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 1); QVERIFY(it != store.begin()); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 2); QVERIFY(it != store.end()); ++it; QCOMPARE(it.resultIndex(), 3); QVERIFY(it != store.end()); ++it; QVERIFY(it == store.end()); QCOMPARE(store.resultAt(0).value<int>(), int0); QCOMPARE(store.resultAt(1).value<int>(), vec0[0]); QCOMPARE(store.resultAt(2).value<int>(), vec0[1]); QCOMPARE(store.resultAt(3).value<int>(), int1); } { ResultStoreInt store; store.addResult(-1, &int0); store.addResults(-1, &vec0); store.addResult(200, &int1); QCOMPARE(store.resultAt(0).value<int>(), int0); QCOMPARE(store.resultAt(1).value<int>(), vec0[0]); QCOMPARE(store.resultAt(2).value<int>(), vec0[1]); QCOMPARE(store.resultAt(200).value<int>(), int1); } { ResultStoreInt store; store.addResult(1, &int1); store.addResult(0, &int0); store.addResult(-1, &int2); QCOMPARE(store.resultAt(0).value<int>(), int0); QCOMPARE(store.resultAt(1).value<int>(), int1); QCOMPARE(store.resultAt(2).value<int>(), int2); } { ResultStoreInt store; QCOMPARE(store.contains(0), false); QCOMPARE(store.contains(1), false); QCOMPARE(store.contains(INT_MAX), false); } { // Test filter mode, where "gaps" in the result array aren't allowed. ResultStoreInt store; store.setFilterMode(true); store.addResult(0, &int0); QCOMPARE(store.contains(0), true); store.addResult(2, &int2); // add result at index 2 QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet. store.addResult(1, &int1); QCOMPARE(store.contains(1), true); QCOMPARE(store.contains(2), true); // 2 should be visible now. store.addResult(4, &int0); store.addResult(5, &int0); store.addResult(7, &int0); QCOMPARE(store.contains(4), false); QCOMPARE(store.contains(5), false); QCOMPARE(store.contains(7), false); store.addResult(3, &int0); // adding 3 makes 4 and 5 visible QCOMPARE(store.contains(4), true); QCOMPARE(store.contains(5), true); QCOMPARE(store.contains(7), false); store.addResult(6, &int0); // adding 6 makes 7 visible QCOMPARE(store.contains(6), true); QCOMPARE(store.contains(7), true); QCOMPARE(store.contains(8), false); } { // test canceled results ResultStoreInt store; store.setFilterMode(true); store.addResult(0, &int0); QCOMPARE(store.contains(0), true); store.addResult(2, &int0); QCOMPARE(store.contains(2), false); store.addCanceledResult(1); // report no result at 1 QCOMPARE(store.contains(0), true); QCOMPARE(store.contains(1), true); // 2 gets renamed to 1 QCOMPARE(store.contains(2), false); store.addResult(3, &int0); QCOMPARE(store.contains(2), true); //3 gets renamed to 2 store.addResult(6, &int0); store.addResult(7, &int0); QCOMPARE(store.contains(3), false); store.addCanceledResult(4); store.addCanceledResult(5); QCOMPARE(store.contains(3), true); //6 gets renamed to 3 QCOMPARE(store.contains(4), true); //7 gets renamed to 4 store.addResult(8, &int0); QCOMPARE(store.contains(5), true); //8 gets renamed to 4 QCOMPARE(store.contains(6), false); QCOMPARE(store.contains(7), false); } { // test addResult return value ResultStoreInt store; store.setFilterMode(true); store.addResult(0, &int0); QCOMPARE(store.count(), 1); // result 0 becomes available QCOMPARE(store.contains(0), true); store.addResult(2, &int0); QCOMPARE(store.count(), 1); QCOMPARE(store.contains(2), false); store.addCanceledResult(1); QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available QCOMPARE(store.contains(0), true); QCOMPARE(store.contains(1), true); QCOMPARE(store.contains(2), false); store.addResult(3, &int0); QCOMPARE(store.count(), 3); QCOMPARE(store.contains(2), true); store.addResult(6, &int0); QCOMPARE(store.count(), 3); store.addResult(7, &int0); QCOMPARE(store.count(), 3); QCOMPARE(store.contains(3), false); store.addCanceledResult(4); store.addCanceledResult(5); QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available QCOMPARE(store.contains(3), true); QCOMPARE(store.contains(4), true); store.addResult(8, &int0); QCOMPARE(store.contains(5), true); QCOMPARE(store.count(), 6); QCOMPARE(store.contains(6), false); QCOMPARE(store.contains(7), false); } { // test resultCount in non-filtered mode. It should always be possible // to iterate through the results 0 to resultCount. ResultStoreInt store; store.addResult(0, &int0); QCOMPARE(store.count(), 1); store.addResult(2, &int0); QCOMPARE(store.count(), 1); store.addResult(1, &int0); QCOMPARE(store.count(), 3); } { ResultStoreInt store; store.addResult(2, &int0); QCOMPARE(store.count(), 0); store.addResult(1, &int0); QCOMPARE(store.count(), 0); store.addResult(0, &int0); QCOMPARE(store.count(), 3); } { ResultStoreInt store; store.addResults(2, &vec1); QCOMPARE(store.count(), 0); store.addResult(1, &int0); QCOMPARE(store.count(), 0); store.addResult(0, &int0); QCOMPARE(store.count(), 4); } { ResultStoreInt store; store.addResults(2, &vec1); QCOMPARE(store.count(), 0); store.addResults(0, &vec0); QCOMPARE(store.count(), 4); } { ResultStoreInt store; store.addResults(3, &vec1); QCOMPARE(store.count(), 0); store.addResults(0, &vec0); QCOMPARE(store.count(), 2); store.addResult(2, &int0); QCOMPARE(store.count(), 5); } { ResultStoreInt store; store.setFilterMode(true); store.addResults(3, &vec1); QCOMPARE(store.count(), 0); store.addResults(0, &vec0); QCOMPARE(store.count(), 2); store.addCanceledResult(2); QCOMPARE(store.count(), 4); } { ResultStoreInt store; store.setFilterMode(true); store.addResults(3, &vec1); QCOMPARE(store.count(), 0); store.addCanceledResults<int>(0, 3); QCOMPARE(store.count(), 2); } { ResultStoreInt store; store.setFilterMode(true); store.addResults(3, &vec1); QCOMPARE(store.count(), 0); store.addCanceledResults<int>(0, 3); QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1 store.addResult(5, &int0); QCOMPARE(store.count(), 3);// result 5 becomes available at index 2 } { ResultStoreInt store; store.addResult(1, &int0); store.addResult(3, &int0); store.addResults(6, &vec0); QCOMPARE(store.contains(0), false); QCOMPARE(store.contains(1), true); QCOMPARE(store.contains(2), false); QCOMPARE(store.contains(3), true); QCOMPARE(store.contains(4), false); QCOMPARE(store.contains(5), false); QCOMPARE(store.contains(6), true); QCOMPARE(store.contains(7), true); } { ResultStoreInt store; store.setFilterMode(true); store.addResult(1, &int0); store.addResult(3, &int0); store.addResults(6, &vec0); QCOMPARE(store.contains(0), false); QCOMPARE(store.contains(1), false); QCOMPARE(store.contains(2), false); QCOMPARE(store.contains(3), false); QCOMPARE(store.contains(4), false); QCOMPARE(store.contains(5), false); QCOMPARE(store.contains(6), false); QCOMPARE(store.contains(7), false); store.addCanceledResult(0); store.addCanceledResult(2); store.addCanceledResults<int>(4, 2); QCOMPARE(store.contains(0), true); QCOMPARE(store.contains(1), true); QCOMPARE(store.contains(2), true); QCOMPARE(store.contains(3), true); QCOMPARE(store.contains(4), false); QCOMPARE(store.contains(5), false); QCOMPARE(store.contains(6), false); QCOMPARE(store.contains(7), false); } { ResultStoreInt store; store.setFilterMode(true); store.addCanceledResult(0); QCOMPARE(store.contains(0), false); store.addResult(1, &int0); QCOMPARE(store.contains(0), true); QCOMPARE(store.contains(1), false); } }