Skip to content
This repository has been archived by the owner on Dec 12, 2023. It is now read-only.

Add support for onResultReadyAt #26

Open
redturtlepower opened this issue Jan 23, 2020 · 1 comment
Open

Add support for onResultReadyAt #26

redturtlepower opened this issue Jan 23, 2020 · 1 comment

Comments

@redturtlepower
Copy link

I was trying to load data one by one, like supported in QFuture::resultReadyAt.

Here is an example:

struct ComplexData{
    QString fruit, color;
};
using ComplexDataPtr = QSharedPointer<ComplexData>;

// Simulate network reply content (QNetworkReply)
QFuture<QString> dataLoaderFuture(){
    return QtConcurrent::run([](){
            QList<QString> list{"Apple,red","Banana,yellow","Orange,orange"};
            auto replyContent = list.join(";");
            qDebug()<<"Sending reply:"<<replyContent;
            return replyContent;
    });
}

// The future holds multiple results, one for each fruit.
QFuture<ComplexDataPtr> getFruitsOneByOne_AsyncFuture(){
    qDebug()<<"Getting fruits one by one (using AsyncFuture).";
    auto defer = AsyncFuture::deferred<ComplexDataPtr>();
    auto reply = dataLoaderFuture(); // returns QString "Apple,red;Banana,yellow;Orange,orange"
    auto observe = AsyncFuture::observe(reply).subscribe([=]() {
        qDebug()<<"Creating fruits from reply";
        QList<ComplexDataPtr> results;
        QString replyContent = reply.result();
        QStringList records = replyContent.split(";");
        auto d = defer;
        int index = 0;
        for ( const auto &record : records ){
            results << createFruitFromRecord(record);
            d.reportResult(results.last(),index++); // DOES NOT WORK AS EXPECTED
        }
        //d.complete(results); // THIS IS NOT WHAT I WANT IN THIS TEST CASE
    });
    return defer.future();
}

The Deferred class lacks a suitable method. I naivly tried to add the method reportResult but it did not work.

void reportStarted() {
     deferredFuture->reportStarted();
 }

 // NOT PART OF ORIGINAL LIBRARY, ADDED BECAUSE
 // I COULD NOT GET "resultReadyAt" SIGNAL TO WORK
 // AND THIS WAS MY ATTEMPT TO IMPLEMENT IT (NO SUCCESS)
 void reportResult(const T &result, int index){
     deferredFuture->reportResult(result, index);
 }
protected:
 QSharedPointer<Private::DeferredFuture<T> > deferredFuture;
};
@vpicaver
Copy link
Contributor

vpicaver commented Mar 19, 2020

I see what you're trying to do, but it's never going to work as descriptive above. Assuming that the defer.future() is being watched (observed) in the same thread as observer(replay).subscribe(). There's no benefit in even doing this because the execution will be synchronous. You might as well use signals / slots from qt or a callback. subscribe() is always called from the main thread. You can have it be called in a secondary thread, if it has a event loop running, with context() instead of subscribe(). The context object that's passed to context() should live in the thread that you want context() to be called. There's several crashing bugs related to context() in the current master, that have been fixed in my fork. The original author (@benlau) seems to be ignoring this repo, btw.

If the defer.future() being observed in a different thread, there might be some benefit.

You might need to call reportStarted() and reportFinished() to get you code working. reportFinished() doesn't exist btw, you'll have to add it just like you did with reportResults()

I hope this helps.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants