深入浅出c++协程丨C++协程实现

本文深入探讨了C++协程的实现,包括boost.coroutine2、C++20协程以及asio中的协程。通过示例展示了如何使用push_type和pull_type在boost中实现协程数据流转,以及C++20协程的初步框架和运行流程。文章还提到了有栈和无栈协程的区别,并讨论了协程在后端开发中的应用。
摘要由CSDN通过智能技术生成

1|0一些实现的c++协程

C++协程实现相关视频讲解:(视频代码资料点击 正在跳转 获取)

协程的实现与原理剖析(上)

协程的实现与原理剖析(下)

协程是一种函数对象,可以设置锚点做暂停,然后再该锚点恢复继续运行,我觉得这是最合适的定义,用户态线程,轻量级线程,可中断恢复的函数,这些都不够精确,先来认识一个boost 1.75的一个例子

#include <iostream>
#include <boost/coroutine2/all.hpp>

void coroutine_function(boost::coroutines2::coroutine<void>::pull_type & coro_back)
{
    std::cout << "a ";
    coro_back(); // 锚点,返回
    std::cout << "b ";
    coro_back(); //锚点 返回
    std::cout << "c ";
}

int main()
{
    boost::coroutines2::coroutine<void>::push_type coroutine_object(coroutine_function); 	// 创建协程
    std::cout << "1 ";
    coroutine_object(); // 运行协程
    std::cout << "2 ";
    coroutine_object(); // 返回锚点,继续运行协程
    std::cout << "3 ";
    coroutine_object(); // 返回锚点,继续运行协程
    return 0;
}
g++ test.cpp -lboost_coroutine -lboost_context -o test
./pull
--------------输出分割线-------------
1 a 2 b 3 c 

在main( )中创建了一个协程 coroutine_object,然后调用coroutine_object()去运行,实际上运行的coroutine_function( )函数,而且每次运行到coro_back();就中断当前的执行返回,下次调用coroutine_object()就从这个断点继续运行,这就是协程的全部了

为什么会有协程是轻量级线程的说法呢?因为协程具有中断可恢复的特性,那么只需要在开一个全局的数组存储所有的协程,在协程中断时,不断轮转调用下一个协程继续运行即可; 这看起来似乎和线程无异,但其实有巨大的区别,因为协程本质是函数,调用协程后原来的地方就会被阻塞,协程处理完了才返回结果,这是天然同步的,而多线程无法做到这点,因为多线程的调度受内核控制,触发点来自于硬件时钟中断不可预见,同时又运行在多核心下,调用后运行次序是不确定的,想实现同步调用就必须通过std::promise/future 去辅佐,但为了性能往往见到的是异步+回调的方式进行多线程的交互,异步回调代码的可读性是很差的而且还需要考虑一大堆并发上锁的情况,协程因其函数本质,是天然同步的,而在遇到阻塞条件时候,把cpu让给别的协程,等条件满足了再通过中断可恢复的特性再继续运行,就实现了并发,同步+并发就是协程强大的地方,其使用范式和轮转+同步非阻塞很像

接下来会介绍一些目前的实现的协程,有非官方的: boost.coroutine2的协程,使用起来方便,让我们可以直观了解协程;微信的libco, 源码很好阅读,资料多,可以进一步学习到协程是如何实现运行的;而官方本身的c++20协程,还不成熟,使用起来比较复杂,官方的东西还是需要提前了解;

C/C++ Linux服务器开发高级架构学习视频点击观看:C/C++Linux服务器开发/Linux后台架构师-学习视频

2|0一些实现的c++协程

2|1boost中的协程

push_type和pull_type

boost自己早就实现了一套协程,先后推出了两个版本boost coroutine和boost coroutine2,现在第一个版本boost coroutine已经弃用, 直接看看coroutin2的简单例子

#include <iostream>
#include <boost/coroutine2/all.hpp>

void foo(boost::coroutines2::coroutine<int>::push_type & sink)
{
    std::cout<<"start coroutine\n";
    sink(1);
    std::cout<<"finish coroutine\n";
}


int main()
{
    boost::coroutines2::coroutine<int>::pull_type source(foo);
    std::cout<<source.get()<<std::endl;
    std::cout<<source()<<std::endl;
    std::cout<<"finish\n";
    return 0;
}

编译链接运行后

g++ pull.cpp -lboost_coroutine -lboost_context -o pull
./pull
--------------输出分割线-------------
start coroutine
1
finish coroutine
finish

boost.corountine2中的协程增加了push_typepull_type用于提供协程数据的流转,约束了数据的从push_type流入,从pull_type流出, 上面的demo定义协程对象source的时候使用了pull_type,所以协程函数参数类型是push_type

 

当协程对象被创建之后就直接运行,直到sink(1)的时候暂停返回

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++协程是一种轻量级的线程,可以在单个线程实现多个协程C++20引入了协程库,其包括协程原语和一些实用程序,使协程的使用变得更加容易。下面是一个简单的C++协程实现demo: ```c++ #include <iostream> #include <coroutine> struct Generator { struct promise_type { int current_value; Generator get_return_object() { return Generator(std::coroutine_handle<promise_type>::from_promise(*this)); } auto initial_suspend() { return std::suspend_always{}; } auto final_suspend() noexcept { return std::suspend_always{}; } void unhandled_exception() {} void return_void() {} auto yield_value(int value) { current_value = value; return std::suspend_always{}; } }; std::coroutine_handle<promise_type> coroutine; Generator(std::coroutine_handle<promise_type> h) : coroutine(h) {} ~Generator() { if (coroutine) coroutine.destroy(); } int get() { coroutine.resume(); return coroutine.promise().current_value; } }; Generator counter(int begin, int end) { for (int i = begin; i <= end; ++i) co_yield i; } int main() { auto gen = counter(1, 5); while (auto value = gen.get()) std::cout << value << ' '; } ``` 这个demo,我们定义了一个生成器(Generator)结构体和一个promise_type结构体。Generator结构体包含一个协程句柄,可以通过该句柄来操作协程。promise_type结构体定义了生成器的类型,并提供了返回对象,挂起,终止等方法。在counter函数,我们使用co_yield关键字来挂起当前协程并返回值。在主函数,我们使用while循环来不断调用协程的get方法来获取生成的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值