Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add C++/WinRT when_any async helper #524

Merged
merged 10 commits into from Jul 22, 2019
Merged

Add C++/WinRT when_any async helper #524

merged 10 commits into from Jul 22, 2019

Conversation

kennykerr
Copy link
Contributor

@kennykerr kennykerr commented Jul 17, 2019

Complements #516 (and improves upon #520) by adding a when_any helper function that will complete when any of the supplied async objects have completed. The resulting async object can then either be waited upon using co_await when_any(...) or when_any(...).get(). In addition, if the async objects are IAsyncOperation or IAsyncOperationWithProgress then the async object created by when_any will also return the result of the first async object to complete.

This is a little harder to implement than when_all, but just as useful for things like redundant operations or cooperative timeouts. As I mentioned in #341, WinRT only allows waiting once. That means that any objects that may not yet have completed may not be waited on again in any way.

Here's an example:

using namespace std::literals;
using namespace winrt;
using namespace Windows::Foundation;

IAsyncOperation<TimeSpan> wait_for(TimeSpan timeout)
{
    co_await timeout;
    printf("wait_for %lld\n", timeout.count());
    co_return timeout;
}

IAsyncAction test()
{
    co_await when_all(wait_for(3s), wait_for(2s), wait_for(1s));
    puts("* when_all returned");

    puts("");

    TimeSpan result = co_await when_any(wait_for(3s), wait_for(2s), wait_for(1s));
    printf("* when_any returned %lld\n", result.count());
}

int main()
{
    init_apartment();
    test().get();
    getchar();
}

And this program produces the following output:

wait_for 10000000
wait_for 20000000
wait_for 30000000
* when_all returned

wait_for 10000000
* when_any returned 10000000
wait_for 20000000
wait_for 30000000

Another example is to use it to implement a cooperative timeout:

template <typename T>
IAsyncOperation<T> get_default_after(T value, TimeSpan timeout)
{
    co_await timeout;
    co_return value;
}

For example:

IAsyncOperation<int> get_the_answer();

int main()
{
    init_apartment();

    int value = when_any(get_the_answer(), get_default_after(0, 2s)).get();
    printf("%d\n", value);
}

And this program will print 42 if it is able to compute it within 2 seconds. Otherwise it prints 0.

@Scottj1s Scottj1s merged commit e9305c0 into master Jul 22, 2019
@Scottj1s Scottj1s deleted the kennykerr-when2 branch July 31, 2019 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants