Search code examples
c++-winrtc++-coroutine

co_await'ed coroutines don't run concurrently in a console application


I don't understand the output of my small code sample.

When I debug inside the MS C++/WinRT code, I see a call to WINRT_TrySubmitThreadpoolCallback() and WINRT_CreateThreadpoolTimer(). I think 3 execution of g() should happen concurrently.

This code:

auto g() -> IAsyncAction {
    Log(L"Entering g()");
    co_await winrt::resume_after(1s);
    Log(L"Exiting g()");
}
auto f() -> IAsyncAction {
    Log(L"Entering f()");
    co_await winrt::resume_background();
    Log(L"First call to g()");
    co_await g();
    Log(L"Second call to g()");
    co_await g();
    Log(L"Third call to g()");
    co_await g();
    Log(L"Exiting f()");
}
auto main() -> int {
    init_apartment();
    f().get();
    return 0;
}

Outputs the following (with the thread ID prefixed):

24000   Entering f()
13160   First call to g()
13160   Entering g()
13160   Exiting g()
13160   Second call to g()
13160   Entering g()
13160   Exiting g()
13160   Third call to g()
13160   Entering g()
13160   Exiting g()
13160   Exiting f()

It does not run instance of g() concurrently. Shouldn't it?

I'm having a conversation about this on Slack (Cpplang#coroutines) where a lot of people are kindly trying to make me understand why my sample code works the way it does. Ast their explanations is not C++/WinRT specific, I hope to have another answer here.

Thank you.


Solution

  • I think 3 execution of g() should happen concurrently.

    C++/WinRT integrates C++ coroutines into the programming model to provide a natural way to cooperatively wait for a result. You can produce your own Windows Runtime asynchronous operation by writing a coroutine. A coroutine is a function like any other in that a caller is blocked until a function returns execution to it. You can use a co_await statement to cooperatively await the result of any function that returns one of these asynchronous operation types.

    This means when you call the g () function, the co_await statement will wait for the operation in the g () method to complete before proceeding. So the behavior is correct. About more details, you can refer to this document.