GoingNative 2013

Bringing await to C++

Download this episode

Download Video

Description

Modern application development requires asynchronous programming techniques. For C++, this generally involves using libraries employing promises or futures or tasks, a la PPL and std::future. What about adding 'await' to the C++ language itself? It's clear that 'await' has done wonders for C#. What would it look like for C++? How does it work? This detailed walkthrough will show the benefits of using ‘await’ vs. PPL or std::future, dig into it's implementation in VC++, and explain the differences between C++ await and C# await. 

Day:

3

Embed

Format

Available formats for this video:

Actual format may change based on video formats available and browser capability.

    The Discussion

    • felix9

      wow wow wow

    • khourig

      Regarding the continuation context of an await, it would be simple to supply the context if await looked more like a function. That is, "await( async_function(), context )" where context is an optional parameter.

    • Marat Abrarov

      They know about Asio! The know (and don't make it a secret) about heaviness of side stack creation for runtime memory (heap?) in a scenario of mass (TCP socket server) usage of "await". They even working over solution for such scenario. VC++ team is really great. Thanks a lot.

    • tomkirbygre​en

      'wow wow wow' is entirely appropriate, at the moment you need to take a dependency on C# and interop to native which is obviously horrible ( all that extra machinery and runtime overhead ). Just hope there's going to be a Visual Studio 2014 so we can get await for C++ into production with a go-live licence as soon as possible. It's too yummy to keep in the labs.

      Then we need the ISO folks to include it in C++ 17.

    • akhare

      Very interesting -- can we expect it in a CTP?  Are parameters to async functions captured and propagated to the side stack? Does this imply a change to the ABI?

    • DeonBrewis

      Thanks for the comments everyone!

      Akhare, yes, we are trying to target the next CTP.

      Parameters to the async function are indeed captured and propagated to the side stack, but it happens inside a trampoline function. The trampoline function thus ensures that there isn't a change in ABI required. i.e. A caller can treat:  "task<T> func() resumable" the same as "task<T> func()".

      In fact, we don't currently have a specific need to put "resumable" on declarations - only on definitions. Hence, it's theoretically completely transparent to callers. We however will require it on declarations for now, just in case. It's easier to remove such a requirement later - not so easy to add it. We've imagined some optimizations if the caller knows it is calling into a resumable function (which will require it on declaration, and thus imply an ABI change), but nothing really concrete.

    • Moondevil

      @tomkirbygreen

      4 years plus the time that at least intel, gcc, clang and vc++ support it, are too long in computer time.

      Who knows how the computing landscape will look like in 2020, time the C++17 should be available in mainstream compilers, maybe.

    • shaoyuan1943

      Interesting!thank you!

    • Mikhail

      You can write a library that does 'await'.

      Please check this - http://habrahabr.ru/post/185706/

      All you need is this code:

      using __Coro=boost::coroutines::coroutine<void()>;
      void Post2UI(const void* coro);
      template<typename L> auto __await_async(const __Coro* coro, __Coro::caller_type& yield, L lambda)->decltype(lambda())
      {
      auto f=async(launch::async, [=](){
      auto r=lambda();
      Post2UI(coro);
      return r;
      });
      yield();
      return f.get();
      }
      void CallFromUI(void* c)
      {
      __Coro* coro=static_cast<__Coro*>(c);
      (*coro)();
      if(!*coro) delete coro;
      }
      #define async_code(block) { __Coro* __coro=new __Coro; *__coro=__Coro([=](__Coro::caller_type& __yield){block});}
      #define await_async(l) __await_async(__coro, __yield, l)

      Plus GUI-specific implementation of two functions - Post2UI and OnAsync, that need to be written once for the whole application on given GUI framework. (It doesn't need to be GUI, it might be somethig like boost::asio::io_service).

    • Evgeny​LPanasyuk

      Full emulation of await feature from C# language in C++ based on Stackful Coroutines from Boost.Coroutine library: https://github.com/panaseleus/await_emu

      int bar(int i)
      {
      auto result = await boost::async([i]{ return reschedule(), i*100; });
      // await "transforms" rest of code into continuation and attaches it to boost::future::then
      // (any other mechanism similar to .then can be used)
      return result + i*10;
      }

      This proof-of-concept shows that exact syntax of await feature can be emulated with help of Stackful Coroutines, demonstrating that it is superior mechanism.

    • fjestis

      How await concept relates to Haskell "bind" and "then" operators used in monads, namely `>>=` and `>>`? Both concepts lead to pretty similar thing I think, especially that iterator-based co-routines.

    • episteme

      GREAT!
      I've tried to use __await/__resumable on C++/CX StoreApp, works fine!

      - f.fukuda, Japan, MVP for Visual C++

    • stepik777

      Resumable functions are like do-notation in Haskell (and await is like <-). But for one specific monad - std::future.

    • Raman_Sharma

    Comments closed

    Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.