Turning a function call which takes a callback into a coroutine

2.3k Views Asked by At

I am exploring and trying to learn C++ Coroutines (added in C++20). An SDK I am using has asynchronous API calls which all take a callback, the callbacks are invoked on some background thread managed by the SDK.


namespace third_party {

bool api_call(const std::string& some_parameter, const std::function<void(std::error_code)>& callback);

} // namespace third_party

I would like wrap this API call into something which can be awaited instead:


namespace my_third_party_sdk_wrapper {

cppcoro::task<std::error_code> api_call(const std::string& some_parameter);
cppcoro::task<std::error_code> api_call(const std::string& some_parameter, cppcoro::cancellation_token token);

} // namespace my_third_party_sdk_wrapper 

I am considering using the cppcoro lib but that isn't a requirement unless the implementation of the wrapper gets much simpler by doing so.

The problem is I cannot figure out how implement the wrapper.

2

There are 2 best solutions below

4
On BEST ANSWER

There's a really good article by Raymond Chen, you can find it here.

In your case, you can do something like this.

namespace my_third_party_async_sdk_wrapper 
{

    auto api_call_async(const std::string& some_parameter)
    {
          struct awaiter : public std::experimental::suspend_always
          {
               awaiter(const std::string &parameter)
               :parameter_(parmeter) {}

               bool await_ready() { return true; }

               void await_suspend(std::experimental::coroutine_handle<> handle)
               { 
                   // use your third party lib call directly here.
                   api_call(parameter_, [](std::error_code ec) 
                   { 
                       // call the handle to resume the coroutine
                       handle(); 
                   }
               }
          };
          return awaiter(some_parameter);
    }

}

This should do what you want.

0
On

a simple (running) example on cppreference.com, "switch_to_new_thread": https://en.cppreference.com/w/cpp/language/coroutines

open are two problems:

  • passing a parameter to the callback
  • chaining the callbacks down the callstack

this code shows a solution https://wandbox.org/permlink/OGjmtFWsgjnn3GxX

look for latest version here: https://github.com/andreaspfaffenbichler/Continuation/blob/master/Continuation.cpp