Asynchronous Programming

The Modern C++ Library provides a Standard C++ language projection for the Windows Runtime. But what about asynchronous programming? Isn’t that ubiquitous in the new Windows API? It sure is and Modern has you covered.

Consider a simple example of trying to connect to a TCP server.

int main()
{
    Initialize();

    StreamSocket socket;
    HostName hostname(L"moderncpp.com");

    socket.ConnectAsync(hostname, L"80").
        Completed([](IAsyncAction const & sender, AsyncStatus)
    {
        try
        {
            sender.GetResults();

            printf("Connected!\n");
        }
        catch (Exception const & e)
        {
            printf("Failed 0x%X\n", e.Result);
        }
    });

    _getch();
}

That works well enough. A lambda is used to respond to the eventual Completed event. Inside the lambda, the GetResults method is used to determine whether the connection was established. Of course, that’s a pretty simple example and would not easily scale to more realistic applications. It is simply not very convenient to coordinate more than a handful of asynchronous events in this manner.

Fortunately, Modern provides adapters to wrap the generic Windows Runtime async actions and operations with PPL tasks. I could rewrite this example more naturally using tasks and continuations as follows.

int main()
{
    try
    {
        Initialize();

        StreamSocket socket;
        HostName hostname(L"moderncpp.com");

        Task(socket.ConnectAsync(hostname, L"80")).then([]
        {
            printf("Connected!\n");
        })
        .wait();
    }
    catch (Exception const & e)
    {
        printf("Failed 0x%X\n", e.Result);
    }
}

Not only is it a lot simpler to chain and coordinate multiple asynchronous operations, Modern ensures that any exception is propagated out of the event handler through to the resumption point so that the caller can deal with any error more naturally.

Great! So if you like PPL you’ll love the support for PPL in Modern C++ for the Windows Runtime. The Concurrency Runtime is an incredible platform for writing scalable and responsive apps. On the other hand, chaining continuations in this manner still results in a lot more typing and code complexity compared with traditional synchronous or blocking APIs.

That’s where the new await keyword comes in with its support for creating resumable functions, otherwise known as stackless coroutines. This is an incredibly simple yet powerful way to write asynchronous code in C++. Here’s a slightly different example using the SyndicationClient class to download a feed.

future<void> Sample()
{
  SyndicationClient client;
  Uri uri(L"http://kennykerr.ca/feed");

  ISyndicationFeed feed = __await client.RetrieveFeedAsync(uri);

  for (ISyndicationItem const & item : feed.Items())
  {
     String title = item.Title().Text();
     printf("%ls\n", title.Buffer());
  }
}

int main()
{
    Initialize();
    Sample().get();
}

The RetrieveFeedAsync method really does – logically at least – return a syndication feed even if it does so asynchronously. The await keyword then stitches together the physical suspension and eventual resumption such that the code may be written in a far more natural style.

Naturally, if a particular async action or operation begins on the application STA, it will likewise resume on the STA when it finally completes. This isn’t always desirable and you can also opt to keep resumption on the thread where the Completed event was originally raised. Exceptions are also propagated back through to resumption both for PPL tasks and resumable functions.

The Modern C++ Library unleashes the Windows Runtime for Standard C++ developers with incredible convenience and the power tools you need.