c++20协程详解(四)

前言

到这就是协程的最后一节了。希望能帮到大家

代码

到这里我们整合下之前二、三节的代码


#include <coroutine>
#include <functional>
#include <chrono>
#include <iostream>
#include <thread>
#include <mutex>
#include <memory>
#include <vector>

struct async_task_base
{
   virtual void completed() = 0;
   virtual void resume() = 0;
};


std::mutex m;
std::vector<std::shared_ptr<async_task_base>> g_event_loop_queue; 
std::vector<std::shared_ptr<async_task_base>> g_resume_queue; //多线程异步任务完成后后,待主线程恢复的线程
std::vector<std::shared_ptr<async_task_base>> g_work_queue; //执行耗时操作线程队列

enum class EnumAwaiterType:uint32_t{
   EnumInitial = 1, //协程initial
   EnumSchduling = 2,// 用户co_await
   EnumFinal = 3//销毁
};


template <typename ReturnType>
struct CoroutineTask;

template <typename CoTask, EnumAwaiterType AwaiterType >
struct CommonAwaiter ;

template <typename>
struct AsyncAwaiter;


template <typename ReturnType>
struct  AsyncThread
{
   using return_type = ReturnType;

   AsyncThread(std::function<return_type ()>&& func): func_(func){

   }
   std::function<return_type ()> func_;
};


template <typename ReturnType>
struct async_task: public async_task_base{
   async_task(AsyncAwaiter<ReturnType> &awaiter)
   :owner_(awaiter)
   {

   }

   void completed() override{
       ReturnType result = owner_.func_();
       owner_.value_ = result;
   }

   void resume() override{
       owner_.h_.resume();
   }
   AsyncAwaiter<ReturnType> &owner_ ;
};


template <typename ReturnType>
struct AsyncAwaiter
{
   using return_type = ReturnType;

   AsyncAwaiter(AsyncThread<ReturnType>& info){
       // std::cout<< " AsyncAwaiter(AsyncThread<ReturnType>& info)" << std::endl;
       value_ = return_type{};
       func_ = info.func_;
   }

   bool await_ready() const noexcept { 
       return false; 
   }
   
   void await_suspend(std::coroutine_handle<> h)  {
       h_ = h;
       std::lock_guard<std::mutex> g(m);
       g_work_queue.emplace_back(std::shared_ptr<async_task_base>( new async_task<uint64_t>(*this)));
   }

   return_type await_resume() const noexcept { 
       return value_;
   }

 
   std::function<return_type ()> func_;
   std::coroutine_handle<> h_; 
   return_type value_ = return_type();
};


template <typename CoTask, EnumAwaiterType AwaiterType>
struct coroutine_task: public async_task_base{
   coroutine_task(CommonAwaiter<CoTask, AwaiterType> &awaiter)
   :owner_(awaiter)
   {

   }

   void completed() override{
   }

   void resume() override{
       if(owner_.h_.done()){
           owner_.h_.destroy();
       }else{
           owner_.h_.resume();
       }
   }
   CommonAwaiter<CoTask,AwaiterType> &owner_ ;
};

template <typename CoTask, EnumAwaiterType AwaiterType = EnumAwaiterType::EnumSchduling>
struct CommonAwaiter 
{
   using return_type =  typename CoTask::return_type;
   using promise_type = typename CoTask::promise_type;
   CommonAwaiter(promise_type* promise):promise_(promise){
   }

   bool await_ready() const noexcept { 
       return false;
   }

   //也可以直接恢复 
   // std::coroutine_handle<> await_suspend(std::coroutine_handle<> h)  {
   //     return h;
   // }

   void await_suspend(std::coroutine_handle<> h)  {
       h_ = h;
       g_event_loop_queue.emplace_back(std::shared_ptr<async_task_base>( new coroutine_task<CoTask, AwaiterType>(*this)) );
   }


   return_type await_resume() const noexcept { 
       return promise_->get_value();
   }

   ~CommonAwaiter(){
   }

   bool resume_ready_= false;
   promise_type* promise_ = nullptr;
   std::coroutine_handle<> h_ = nullptr;
};


template <typename CoTask>
struct CommonAwaiter<CoTask, EnumAwaiterType::EnumInitial>
{
   CommonAwaiter(){
   }

   bool await_ready() const noexcept { 
       return true;
   }

   void await_suspend(std::coroutine_handle<>)  {
   }

   void await_resume() const noexcept { 
   }

   ~CommonAwaiter(){
   }
};



template <typename CoTask>
struct CommonAwaiter <CoTask, EnumAwaiterType::EnumFinal>
{
   CommonAwaiter(){
   }

   bool await_ready() noexcept { 
       return false;
   }

   void await_suspend(std::coroutine_handle<> h)  noexcept{
       h_ = h;
       g_event_loop_queue.emplace_back(std::shared_ptr<async_task_base>( new coroutine_task<CoTask, EnumAwaiterType::EnumFinal>(*this)));
   }

   void await_resume()  noexcept{ 
   }

   std::coroutine_handle<> h_ = nullptr;
};


template<typename CoTask>
struct Promise
{
   using return_type  = typename CoTask::return_type ;
   ~Promise(){
   }
   CommonAwaiter<CoTask, EnumAwaiterType::EnumInitial> initial_suspend() {
       return {}; 
   };
   
   CommonAwaiter<CoTask, EnumAwaiterType::EnumFinal> final_suspend() noexcept { 
       return {}; 
   }

   void unhandled_exception(){
       std::rethrow_exception(std::current_exception());
   }

   CoTask get_return_object(){ 
       return  CoTask(this);
   }

   return_type get_value() {
       return value_;
   }


   void return_value(return_type value){
       value_ = value;
   }
  
   template<typename T>
   CommonAwaiter<CoroutineTask<T>> await_transform(CoroutineTask<T> &&task){
       return CommonAwaiter<CoroutineTask<T>>(task.p_);
   }

 
   template<typename T>
   inline AsyncAwaiter<T> await_transform(AsyncThread<T>&& info)
   {
       return AsyncAwaiter(info);
   }



   return_type value_;
};

template <typename ReturnType>
struct CoroutineTask{

   using return_type  = ReturnType;
   using promise_type = Promise<CoroutineTask>;

   CoroutineTask(const CoroutineTask &other) = delete;
   CoroutineTask(const CoroutineTask &&other) = delete;
   CoroutineTask& operator=(const CoroutineTask&) {};
   CoroutineTask& operator=(const CoroutineTask&&) = delete;

   CoroutineTask(promise_type* promise) {
       p_ = promise;
       
   }

   promise_type *p_ = nullptr;

};


void do_work() {
   while (1)
   {
       std::lock_guard<std::mutex> g(m);
       for(auto task : g_work_queue){
           task->completed();
           g_resume_queue.push_back(task);
       }
       
       g_work_queue.clear();
   }   
   
}

void run_event_loop(){
   std::vector<std::shared_ptr<async_task_base>> g_raw_work_queue_tmp;
   std::vector<std::shared_ptr<async_task_base>> g_event_loop_queue_temp;
   while(1){
       g_raw_work_queue_tmp.clear();
       g_event_loop_queue_temp.clear();
       {
           g_event_loop_queue_temp.swap(g_event_loop_queue);
           std::lock_guard<std::mutex> g(m);
           g_raw_work_queue_tmp.swap(g_resume_queue);
       }
       
       for(auto &task : g_raw_work_queue_tmp){
           task->resume();
       }

       for(auto task : g_event_loop_queue_temp){
           task->resume();
       }

   }
}


// ------------------------------------------------------------------------------------------------------



template <typename ReturnType>
AsyncThread<ReturnType> do_slow_work(std::function< ReturnType () > &&func){
   return AsyncThread<ReturnType>(std::forward< std::function< ReturnType () > >(func));
}


CoroutineTask<u_int64_t> second_coroutine(){
   co_return 3;
}

CoroutineTask<float> third_coroutine(){
   co_return 3.1;
}


CoroutineTask<char> first_coroutine(){
   int a = 1;
   auto func =[&]() -> uint64_t{
       // std::cout<< "do a slow work !!!!!!!!!!!!!!!!!!!!!" << std::endl;
       return a;
   };  
   uint64_t result = co_await do_slow_work<uint64_t>(func);
   std::cout << "@@@@@@@@@ result1 is  : " << result  << std::endl;  
   a = 2;
   result = co_await do_slow_work<uint64_t>(func);
   std::cout << "@@@@@@@@@ result2 is  : " << result  << std::endl; 
   uint64_t num =  co_await second_coroutine();
   std::cout << "@@@@@@@@@ second_coroutine result is  : " << num  << std::endl; 
   a = 3;
   result = co_await do_slow_work<uint64_t>(func);
   std::cout << "@@@@@@@@@ result3 is  : " << result  << std::endl;  
   float num2 =  co_await third_coroutine();
   a = 4;
   result = co_await do_slow_work<uint64_t>(func);
   std::cout << "@@@@@@@@@ third_coroutine result is  : " << num2  << std::endl; 
   result = co_await do_slow_work<uint64_t>(func);
   std::cout << "@@@@@@@@@ result4 is  : " << result  << std::endl;  
   co_return 'b';
}


CoroutineTask<char> Coroutine(){
   int a = 1;
   auto func =[&]() -> uint64_t{
       // std::cout<< "do a slow work !!!!!!!!!!!!!!!!!!!!!" << std::endl;
       return a;
   };  
   uint64_t result = co_await do_slow_work<uint64_t>(func);
   std::cout << "@@@@@@@@@ result is  : " << result  << std::endl; 
   uint64_t num =  co_await second_coroutine();
   std::cout << "@@@@@@@@@ coroutine result is  : " << num  << std::endl; 

   co_return 'b';
}


void test_func(){
   Coroutine();
   first_coroutine();
}

int main(){
   test_func();
   std::thread work_thread(do_work);
   run_event_loop();
   return 0;
}

分析

将对两种awaiter的co_await操作规则定义到promise中
在这里插入图片描述
对co_await可以使用await_transform 和重载co_await运算符,但是两种用法不能同时存在。

在这里插入图片描述
优先恢复其他线程完成耗时任务的协程,再进行当前线程中的协程挂起、销毁、恢复调度。

协程函数相对对于协程的优势

协程每次都会在final_suspend和initial_suspend时创建awaiter,以及对awaiter挂起,在for循环中,这样显然不科学,但异步函数只有一个awaiter,在for循环中更合适。

运行结果

在这里插入图片描述

待扩展

异步io

如果对使用epoll实现网络io异步函数感兴趣,可以自行实现,实现方式和实现多线程异步函数一样,这里就不实现了,注意下epoll中,不能添加普通文件系统fd。

协程超时机制

可以加上定时器对async_task_base进行超时检查,以此来支持协程超时

流程图

最后附上co_await Coroutine()的流程图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/524996.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

24上教资面试报名时间汇总⏰报名流程✅

24上教资面试报名公告已经发布&#xff01; &#x1f4a1;报名地址&#xff1a;中小学教师资格考试网 &#x1f550;报名时间&#xff1a;4月12日开始 广东&#xff1a;4月12日10:00-15日17:00 河北&#xff1a;4月12日10:00至4月15日17:00 广西&#xff1a;4月12日10:00至15日…

深入理解Vue 3.0中的watch属性immediate和deep的用法

摘要&#xff1a; 在 Vue 3.0 中&#xff0c;watch 是一个用于观察和响应组件中数据变化的强大工具。它允许我们监听组件中的属性、对象或数组的变化&#xff0c;并执行相应的回调函数。除了基本的用法外&#xff0c;watch 还提供了两个扩展选项&#xff1a;immediate 和 deep…

【JavaScript】原型链/作用域/this指针/闭包

1.原型链 参考资料&#xff1a;Annotated ES5 ECMAScript起初并不支持如C、Smalltalk 或 Java 中“类”的形式创建对象&#xff0c;而是通过字面量表示法或者构造函数创建对象。每个构造函数都是一个具有名为“prototype”的属性的函数&#xff0c;该属性用于实现基于原型的继…

【氮化镓】在轨实验研究辐射对GaN器件的影响

【Pioneering evaluation of GaN transistors in geostationary satellites】 摘要&#xff1a; 这篇论文介绍了一项为期6年的空间实验结果&#xff0c;该实验研究了在地球静止轨道上辐射对氮化镓&#xff08;GaN&#xff09;电子元件的影响。实验使用了四个GaN晶体管&#xf…

H3C防火墙RBM对接交换机M-LAG典型配置

FW配置&#xff1a;FW1与FW2采用RBM组网&#xff0c;M-LAG Border的跨设备二层聚合口与RBM FW设备的设备内三层聚合口对接。FW主设备的设备内三层聚合口编号应与备设备的设备内三层聚合口编号保持一致。防火墙省略安全域和安全策略配置。 Border设备配置&#xff1a;采用M-LAG组…

嵌入式学习49-单片机2

指令周期 1M 机器周期 12M &#xff08;晶体震荡器产生&#xff09; 中断两种方式 …

创建型模式--1.单例模式【巴基速递】

1. 巴基的订单 在海贼世界中&#xff0c;巴基速递是巴基依靠手下强大的越狱犯兵力&#xff0c;组建的集团海贼派遣公司&#xff0c;它的主要业务是向世界有需要的地方输送雇佣兵&#xff08;其实是不干好事儿&#xff09;。 自从从特拉法尔加罗和路飞同盟击败了堂吉诃德家族 &…

怎么把学浪的视频保存到手机

越来越多的人在学浪app里面购买了课程并且想要下载下来&#xff0c;但是苦于没有方法或者工具&#xff0c;所以本文将教大家如何把学浪的视频保存到手机随时随地的观看&#xff0c;再也不用担心课程过期的问题。 本文将介绍工具来下载&#xff0c;因为下载方法太复杂&#xff…

Yolov5改进算法之添加Res2Net模块

目录 1. Res2Net介绍 1.1 Res2Net的背景和动机 1.2 Res2Net的基本概念 2. YOLOV5添加Res2Net模块 Res2Net&#xff08;Residual Resolution Network&#xff09;是一种用于图像处理和计算机视觉任务的深度卷积神经网络架构。它旨在解决传统的ResNet&#xff08;Residual Ne…

【JVM性能调优】- 阿里在线排除工具 - Arthas

阿里在线排除工具 - Arthas Arthas&#xff08;阿尔萨斯&#xff09;是阿里开源的一款Java在线诊断工具&#xff0c;官网原话&#xff1a;当你遇到以下类似问题而束手无策时&#xff0c;Arthas可以帮助你解决&#xff1a; 这个类从哪个 jar 包加载的&#xff1f;为什么会报各种…

千视携 NDI 6 轻量化媒体方案亮相北京CCBN展会

展会简介 第30届中国国际广播电视网络技术展览会&#xff08;CCBN&#xff09;将于4月24至26日在北京首钢会展中心举行。此次展会将汇集全球各大数字媒体、广播电视单位以及IT、通信技术厂商。展会重点关注数字化转型、智能媒体、融媒体等主题&#xff0c;并展示最新的5G、4K/8…

Day107:代码审计-PHP模型开发篇MVC层RCE执行文件对比法1day分析0day验证

目录 MVC 架构 CNVD-代码执行1day-lmxcms1.40版本 CNVD-命令执行1day-baijiacms4.1.4版本 知识点&#xff1a; 1、PHP审计-MVC开发-RCE&代码执行 2、PHP审计-MVC开发-RCE&命令执行 3、PHP审计-MVC开发-RCE&文件对比 MVC 架构 MVC流程&#xff1a; Controller截…

HCLR-Net: 混合对比学习正则化与局部随机扰动用于水下图像增强

论文地址&#xff1a;https://doi.org/10.1007/s11263-024-01987-y 源码&#xff1a;https://github.com/zhoujingchun03/HCLR-Net 摘要&#xff1a; 由于水下环境复杂多样&#xff0c;导致光吸收、散射和色彩失真等严重退化现象&#xff0c;因此水下图像增强是一项重大挑战…

Day108:代码审计-PHP模型开发篇MVC层动态调试未授权脆弱鉴权未引用错误逻辑

目录 案例1-Xhcms-动态调试-脆弱的鉴权逻辑 案例2-Cwcms-动态调试-未引用鉴权逻辑 案例3-Bosscms-动态调试-不严谨的鉴权逻辑 知识点&#xff1a; 1、PHP审计-动态调试-未授权安全 2、PHP审计-文件对比-未授权安全 3、PHP审计-未授权访问-三种形态 动态调试优点: 环境配置&…

Embedding:跨越离散与连续边界——离散数据的连续向量表示及其在深度学习与自然语言处理中的关键角色

Embedding嵌入技术是一种在深度学习、自然语言处理&#xff08;NLP&#xff09;、计算机视觉等领域广泛应用的技术&#xff0c;它主要用于将高维、复杂且离散的原始数据&#xff08;如文本中的词汇、图像中的像素等&#xff09;映射到一个低维、连续且稠密的向量空间中。这些低…

1111111111111111111111111

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

活动图高阶讲解-15

1 00:00:00,000 --> 00:00:07,200 目前来说&#xff0c;这个菱形到底是分还是合 2 00:00:07,200 --> 00:00:13,600 这个是靠入边出边的数量来判断的 3 00:00:13,600 --> 00:00:22,560 有的方法学&#xff0c;它可能会这样搞一些花样 4 00:00:22,560 --> 00:00:2…

Adobe InDesign 2024 v19.3 (macOS, Windows) - 版面设计和桌面出版软件

Adobe InDesign 2024 v19.3 (macOS, Windows) - 版面设计和桌面出版软件 Acrobat、After Effects、Animate、Audition、Bridge、Character Animator、Dimension、Dreamweaver、Illustrator、InCopy、InDesign、Lightroom Classic、Media Encoder、Photoshop、Premiere Pro、Ad…

室友打团太吵?一条命令让它卡死

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;更多干货&#xff0c;请关注专栏《网络安全自学教程》 SYN Flood 1、hping3实现SYN Flood1.1、主机探测1.2、扫描端…

鸿蒙(HarmonyOS)APP开发实战课程(入门到精通)

2024培训课程 2024技术交流群 CSDN在线课程地址: https://edu.csdn.net/course/detail/39448 推荐阅读 鸿蒙Harmony OS核心架构 鸿蒙内核源码分析(系统调用篇) 鸿蒙(HarmonyOS)APP开发培训课程 鸿蒙(HarmonyOS)APP开发实战课程 鸿蒙系统&#xff08;HarmonyOS&#xff0…