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

Allow querying Combinator whether or not any futures have been added #6

Open
daniel-adb-fa opened this issue Feb 12, 2018 · 3 comments

Comments

@daniel-adb-fa
Copy link
Contributor

My motivation is the following use case:

I have a result that depends on an arbitrary number of inputs, where arbitrary means: possibly also 0. Each of the inputs can either be immediately available or require delegation to a thread. Now I use AsyncFuture::Combinator to detect when all the results are ready.

My first attempt looked like this:

[...]
auto combiner = AsyncFuture::combine();
QVector<QFuture<Result>> results;
for(auto item: items) {
    auto future = getCachedResultOrCompute(item);
    results << future;
    combiner << future; 
}
return combiner.subscribe([results]() {
   // do something with the results...
}).future();

This approach has one problem though: If items is empty, the callback given to subscribe will never get called. So, it'd be convenient if it were possible to write something like the following wrapper to subscribe on Combinator:

template<typename RetType, typename Func>
inline QFuture<RetType> subscribeToCombinator(Func f, AsyncFuture::Combinator combinator)
{
	auto cancelToken = AsyncFuture::deferred<void>();
	if(combinator.isEmpty()) {
             auto rv = AsyncFuture::deferred<RetType>();
             rv.complete(RetType());
             return rv.future();
	}

	return combinator.subscribe(f).future();
}

This requires a method isEmpty (or whatever you'd like to call it) on Combinator, allowing the client to query whether or not there is already a QFuture on Combinator. As far as I can see, it is easily implented by adding the following code to Combinator:
bool isEmpty() const { return combinedFuture->count == 0; }

@benlau
Copy link
Owner

benlau commented Mar 2, 2018

Hello,

I would suggest an alternative approach. In the latest master branch, I have make the Combinator to support to set progressValue , progressMaximum value.

        auto d1 = timeout(50);
        auto d2 = timeout(60);
        auto d3 = timeout(30);

        auto combinator = combine();

        combinator << d1 << d2 << d3;

        auto future = combinator.future();
        QCOMPARE(future.progressValue(), 0);
        QCOMPARE(future.progressMaximum(), 3);

        await(future);

        QCOMPARE(future.progressValue(), 3);
        QCOMPARE(future.progressMaximum(), 3);

So that you could query the no. of added future by using combinator.future().progressMaximum()

@daniel-adb-fa
Copy link
Contributor Author

Okay, this looks nice. So QFutureInterface guarantees progressMaximum() to return zero before any call to setProgressRange has been made?
To make this expectation explicit, I'd suggest we should add another

QCOMPARE(future.progressMaximum(), 0);

just after the intialisation of combinator to the test.

@benlau
Copy link
Owner

benlau commented Mar 2, 2018

yes, it should be guaranteed to set to zero. I will add the test case.

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