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, //协程initialEnumSchduling = 2,// 用户co_awaitEnumFinal = 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()的流程图

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

抖音-引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域,

抖音-引流私域转化模式1.0现场视频&#xff0c;从抖音源源不断把人加到私域&#xff0c;让加到私域的粉丝买单 抖音-引流私域转化模式1.0现场视频&#xff0c;从抖音源源不断把人加到私域 - 百创网-源码交易平台_网站源码_商城源码_小程序源码 课程内容&#xff1a; 01.第一…

1.8.3 卷积神经网络近年来在结构设计上的主要发展和变迁——GoogleNet/inception-v1

1.8.3 卷积神经网络近年来在结构设计上的主要发展和变迁——GoogleNet/ inception-v1 前情回顾&#xff1a; 1.8.1 卷积神经网络近年来在结构设计上的主要发展和变迁——AlexNet 1.8.2 卷积神经网络近年来在结构设计上的主要发展和变迁——VGGNet GoogleNet问题 在VGGNet简单堆…

zookeeper中的znode节点的一些功能和应用

zookeeper是一个挺好玩的东西 有着独特的选举机制&#xff0c;一般在中小型集群中&#xff0c;zookeeper一般装在三个节点 其中只有一个节点对外提供服务&#xff0c;处于leader状态&#xff0c;另外两台未follower状态 这得益于zookeeper独特的选举机制&#xff0c;可以保证le…

智慧园区革新之路:山海鲸可视化技术引领新变革

随着科技的飞速发展&#xff0c;智慧园区已成为城市现代化建设的重要组成部分。山海鲸可视化智慧园区解决方案&#xff0c;作为业界领先的数字化革新方案&#xff0c;正以其独特的技术优势和丰富的应用场景&#xff0c;引领着智慧园区建设的新潮流。 本文将带大家一起了解一下…

Lumos学习王佩丰Excel第二讲:单元格格式设置

今天学会GIF录制了&#xff0c;分享知识会更简便一些&#xff0c;话不多说&#xff0c;开始吧~ 一、美化表格 1、设置单元格格式的路径 从菜单栏进入&#xff1a; 选中区域&#xff08;单元格&#xff09;- 右键“设置单元格格式”&#xff1a; 2、合并单元格 合并一行 批量…

约跑小程序源码(asp.net+vue+element++uniapp+sqlserver)

开发语言&#xff1a;c# 框架&#xff1a;后端 asp.net mvc pc管理页面&#xff1a;vueelement 数据库&#xff1a;sqlserver 开发软件&#xff1a;eclipse/myeclipse/idea 浏览器&#xff1a;谷歌浏览器 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X …

初识Java中的NIO

1.概述 Java NIO 全称java non-blocking IO &#xff0c;是指 JDK 提供的新 API。从 JDK1.4 开始&#xff0c;Java 提供了一系列改进的输入/输出新特性&#xff0c;被统称为 NIO(即 New IO)&#xff0c;是同步非阻塞的。NIO采用内存映射文件的方式来处理输入输出&#xff0c;NI…

OSPF实例是什么?

OSPF实例是什么&#xff1f; **OSPF实例指的是一个OSPF路由进程&#xff0c;它是在一个设备上运行的单独的OSPF路由协议实体**。 在详细解释这个概念之前&#xff0c;需要了解OSPF&#xff08;Open Shortest Path First&#xff09;是一种内部网关协议&#xff08;IGP&#x…

lua学习笔记9(字典的学习)

print("********************字典的学习***********************") a{["凌少"]"傻逼",["我"]"天才",["age"]24,["daihao"]114514,["8848"]20000} --访问单个变量 print(a["凌少"])…

非机构化解析【包含PDF、word、PPT】

此项目是针对PDF、docx、doc、PPT四种非结构化数据进行解析&#xff0c;识别里面的文本和图片。 代码结构 ├── Dockerfile ├── requirements ├── resluts ├── test_data │ ├── 20151202033304658.pdf │ ├── 2020_World_Energy_Data.pdf │ ├── …

【CSS】新闻页面制作 案例一

&#xff08;大家好&#xff0c;今天我们将通过案例实战对之前学习过的CSS知识进行复习巩固&#xff0c;大家和我一起来吧&#xff0c;加油&#xff01;&#x1f495;&#xff09; 目录 一、前述 二、素材 案例文字素材 案例图片素材 三、案例分析 四、案例实施 五、应用…

基于Spring Boot的旅游管理系统设计与实现

基于Spring Boot的旅游管理系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 旅游方案&#xff0c;用户通过旅游方案可以查看方案编号…