Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-140786

QFuture::cancelChain doesn't set the cancel info to all chained futures/promises

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P2: Important P2: Important
    • None
    • 6.10.0 RC
    • Core: Threads
    • None
    • 8
    • Foundation Sprint 140, Foundation Sprint 141

      As the title says, QFuture::cancelChain cancels the chain but it doesn't propagate the info down the chain. 

      The canceled info down the chain is very important as it's the only way to cancel the pending operation.

       

      Here is a simple unit test to show the problem.

       

      void MyTest::testQFuture_cancelChain()
      {
          QSemaphore start;
          QSemaphore cont;    
          auto futureBuilder = [&](bool canceledB4, bool canceledAfter) {
              return QtConcurrent::run(
                  [&](QPromise<void> &promise, bool canceledB4, bool canceledAfter) {
                      QCOMPARE(promise.isCanceled(), canceledB4);
                      start.release(1);
                      cont.acquire(1);
                      QCOMPARE(promise.isCanceled(), canceledAfter);
                  },
                  canceledB4, canceledAfter);
          };    
      
          // 1st chain cancel
          {
              auto future = futureBuilder(false, true)
                           .then([] { QVERIFY(false); })
                           .onCanceled([] { QVERIFY(true); });
              start.acquire(1);
              future.cancelChain();
              cont.release(1);
              future.waitForFinished();
          }    
      
          // 2nd chain cancel
          {
              auto future = futureBuilder(false, false)
                                .then([&](const QFuture<void> &innerFuture) {
                                    QCOMPARE(innerFuture.isCanceled(), false);
                                    start.release(1);
                                    // should be canceled by "future.cancelChain()" below
                                    cont.acquire(1);
                                    QCOMPARE(innerFuture.isCanceled(), true);
                                })
                                .onCanceled([] { QVERIFY(false); })
                                .then([] { QVERIFY(false); })
                                .onCanceled([] { QVERIFY(true); });
              start.acquire(1);
              cont.release(1);
              start.acquire(1);
              future.cancelChain(); // should cancel the innerFuture from first ".then"
              cont.release(1);
              future.waitForFinished();
          }    
      
          // Wrapped chain cancel
          {
              auto future = futureBuilder(false, false)
                                .then([&]() {
                                    // This "wrapped future" should be canceled by "future.cancelChain()" below
                                    return futureBuilder(false, true);
                                })
                                .unwrap()
                                .then([] { QVERIFY(false); })
                                .onCanceled([] { QVERIFY(true); });
              start.acquire(1);
              cont.release(1);
              start.acquire(1);
              future.cancelChain(); // should cancel the "wrapped" future from first ".then"
              cont.release(1);
              future.waitForFinished();
          }
      }
      
      

        For Gerrit Dashboard: QTBUG-140786
        # Subject Branch Project Status CR V

            ivan.solovev Ivan Solovev
            taipan BogDan Vatra
            Vladimir Minenko Vladimir Minenko
            Alex Blasche Alex Blasche
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:

                There is 1 open Gerrit change