C++ 各编译器对协程支持情况(时间点 2018.08 )

N4760

N4760 是 C++标准中对协程支持的最新提案。 内容为:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4760.pdf

目前已经有不少编译器对它做了支持:

  • MSVC

    https://blogs.msdn.microsoft.com/vcblog/2017/01/27/yield-keyword-to-become-co_yield-in-vs-2017/
    https://blogs.msdn.microsoft.com/vcblog/2017/02/02/using-ibuv-with-c-resumable-functions/

  • CLang

    http://clang.llvm.org/cxx_status.html#ts

目前最主要的问题是 GCC 尚未开始对其做支持 : https://gcc.gnu.org/projects/cxx-status.html#tses

使用该提案的例子展示

Boost Asio 中有例子:

https://www.boost.org/doc/libs/1_68_0/doc/html/boost_asio/example/cpp17/coroutines_ts/echo_server.cpp

下面摘至以上链接部分代码:

awaitable listener()
{
  auto executor = co_await this_coro::executor();
  auto token = co_await this_coro::token();

  tcp::acceptor acceptor(executor.context(), {tcp::v4(), 55555});
  for (;;)
  {
    tcp::socket socket = co_await acceptor.async_accept(token);
    co_spawn(executor,
        [socket = std::move(socket)]() mutable
        {
          return echo(std::move(socket));
        },
        detached);
  }
}

int main()
{
  try
  {
    boost::asio::io_context io_context(1);

    boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
    signals.async_wait([&](auto, auto){ io_context.stop(); });

    co_spawn(io_context, listener, detached);

    io_context.run();
  }
  catch (std::exception& e)
  {
    std::printf("Exception: %s\n", e.what());
  }
}

可以看到:

  • co_spawn 创建 1 个新协程
  • co_await 设置协程可主动让出 CPU 片的代码点

C++ 标准需要支持协程的重要性

引用下微软团队的话吧:

下面内容摘至 :https://blogs.msdn.microsoft.com/vcblog/2017/02/02/using-ibuv-with-c-resumable-functions/

Problem Space

Waiting for disks or data over a network is inherently slow and we have all learned (or been told) by now that writing software that blocks is bad, right? For client side programs, doing I/O or blocking on the UI thread is a great way to create a poor user experience as the app glitches or appears to hang. For server side programs, new requests can usually just create a new thread if all others are blocked, but that can cause inefficient resource usage as threads are often not a cheap resource.

However, it is still remarkably difficult to write code that is efficient and truly asynchronous. Different platforms provide different mechanisms and APIs for doing asynchronous I/O. Many APIs don’t have any asynchronous equivalent at all. Often, the solution is to make the call from a worker thread, which calls a blocking API, and then return the result back to the main thread. This can be difficult as well and requires using synchronization mechanisms to avoid concurrency problems. There are libraries that provide abstractions over these disparate mechanisms, however. Examples of this include Boost ASIO, the C++ Rest SDK, and libuv. Boost ASIO and the Rest SDK are C++ libraries and libuv is a C library. They have some overlap between them but each has its own strengths as well.

上面的文字大致说了 2 个问题:

  • 阻塞操作会使线程挂起,只能通过开新线程来维持程序继续工作。而多开线程是效率低下的
  • 虽然有些产品提供了异步 I/O ,但更多的 API 无法异步操作。典型例子如 mysql client api 等。只能以问题1中描述的方法去使用。

因此 C++ 标准引入协程是有重大意义的:

  • 并发编程模式简化
  • 可以预见,基于协程的 mysql 库等,就会出现
  • 后端 C++ 程序对 CPU 利用率上会做的更好

等等

以上

你可能感兴趣的:(linux,协程,C++标准提案)