将接受回调的函数调用转换为协程

Turning a function call which takes a callback into a coroutine

我正在探索并尝试学习 C++ 协程(在 C++20 中添加)。我正在使用的一个 SDK 具有异步 API 调用,它们都接受回调,回调是在 SDK 管理的某些后台线程上调用的。


namespace third_party {

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

} // namespace third_party

我想将此 API 调用包装到可以等待的内容中:


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 

我正在考虑使用 cppcoro 库,但这不是必需的,除非这样做使包装器的实现变得更加简单。

问题是我不知道如何实现包装器。

陈峰的文章写得真好,你可以找找here

对于你的情况,你可以这样做。

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 false; }

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

          };
          return awaiter(some_parameter);
    }

}

这应该可以满足您的要求。

关于 cppreference.com、“switch_to_new_thread”的简单 (运行) 示例:https://en.cppreference.com/w/cpp/language/coroutines

打开有两个问题:

  • 向回调传递参数
  • 将回调链接到调用堆栈

此代码显示了一个解决方案 https://wandbox.org/permlink/OGjmtFWsgjnn3GxX

在此处查找最新版本:https://github.com/andreaspfaffenbichler/Continuation/blob/master/Continuation.cpp