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

      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();
          }
      }
      
      

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            ivan.solovev Ivan Solovev
            taipan BogDan Vatra
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:

                There are no open Gerrit changes