C++协程线程
等待--恢复
,等待
是挂起,协程
执行完,再恢复.类似烧开水
.
c++20
协程几个基本概念:
可恢复类型
用于恢复协程
类型,对应协程
就是协程返回类型
,调用者
可通过它恢复
协程,也可通过内部承诺型
拿到协程返回值
.
承诺类型
主要用来保存
协程值,如果需要恢复协程
时,需要通过承诺类型
拿到协程句柄
,再调用它的恢复
方法.
协程句柄
主要用于访问底层
协程帧,恢复和释放
协程帧.
依赖顺序是可恢复类型-->承诺类型-->协程句柄
,调用者
通过可恢复类型
来恢复
协程并拿到协程值
.
协待,等待器,可等待
通过协待式
来实现"等待
",协待
本质就是等待懒
任务执行完成并拿到返回值
,它主要依赖等待器
来实现这个"等待
"机制,可等待
是帮助获取等待器
的,不用太关注.
等待器
如何实现等待,并取懒
任务返回值的呢?
等待器.准备好协
返回假
时,就会挂起
协程,然后会执行等待器.挂起协
,在挂起协
中去调用懒
的任务
,典型场景是把任务
丢到线程中,或发起异步操作(注意要把协程句柄
传到线程或异步回调
里面),然后就返回给调用者
,调用者
不会阻塞,可以继续向下执行;
懒
的任务
执行完成后,就可调用前面传入
的协程句柄.恢复
来恢复协程表示懒
的任务
执行完了,这时可通过等待器.恢复协
得到懒任务
的返回值了(也可能是空
无返回值);接下来就会从协待
下一行继续执行协程
函数直到协中
.
依赖
顺序是承诺类型-->初化挂起
返回的等待器-->止挂起
返回的等待器
.
初化挂起
挂起的目的
很清楚,就是等待
要完成的懒任务
,具体由等待器
来负责,那么何时需要止挂起
呢,典型场景是同步等待协程完成
时.
所以c++20
协程中最重要
的两个对象就是可恢复类型
(恢复)和等待器
(等待),其它都是"工具人
",协程关键
是要设计好如何使两个对象
协作好.
等待线程中的协程执行完
常见实用协程使用场景
是在线程
中执行协程,这也是协程设计
的重要目标:化"异步"为"同步!
,通过简单代码来看看,如何调度协程
到线程
中执行吧:
元<型名 T>
构 承诺;
元<型名 T>
构[[未丢弃]]任务{
用 承诺类型=承诺<T>;
任务()=默认;
动 符号 协待()常 无异{
构 等待器{
极 准备好协()常 无异{
中 承诺.是准备好();
}
用 协程句柄=协程句柄<>;
协程句柄 挂起协(协程句柄 连续)常 无异{
承诺.连续=连续;
中 协程句柄<承诺<T>>::从承诺(承诺);
}
T&&恢复协()常{
中 承诺.取结果();
}
承诺<T>&承诺;
};
中 等待器{*承诺};
}
T&&取结果(){
中 承诺->取结果();
}
私:
任务(承诺<T>*承诺):承诺{承诺}{}
承诺<T>*承诺=空针;
元<型名>友 构 承诺;
};
元<型名 T>
构 承诺{
动 取中对象(){
中 任务<T>{本};
}
从不挂起 初始挂起()无异{中{};}
动 止挂起()无异{
构 止等待器{
极 准备好协()常 无异{中 假;}
空 挂起协(协程句柄<承诺<T>>本协程)无异{
动&承诺=本协程.承诺();
如(承诺.连续)
承诺.连续();
}
空 恢复协()常 无异{}
};
中 止等待器{};
}
空 未处理异常(){终止();}
元<型名 U>
空 返回值(U&&值)
{
结果.元 原位<1>(前向<U>(值));
}
T&&取结果(){
如(结果.索引()==2)
再抛异常(取<2>(结果));
中 移动(取<1>(结果));
}
极 是准备好(){
中 结果.索引()!=0;
}
变量<单态,T,异常针>结果;
协程句柄<>连续;
};
构 异步读文件{
异步读文件(文系::路径 路径):路径{移动(路径)}{}
极 准备好协()常 无异{中 假;}
空 挂起协(协程句柄<>协程){
动 工作=[本,协程]()可变{
输出<<本线程::取标识()<<"工作者线程:打开文件";
动 流=入文件流{路径};
输出<<本线程::取标识()<<"工作者线程:读文件";
结果.赋值(入流缓冲步<符>{流},
入流缓冲步<符>{});
输出<<本线程::取标识()<<"工作者线程:恢复协程";
协程();
输出<<本线程::取标识()<<"工作者线程:退出";
};
线程{工作}.分离();
}
串 恢复协()无异{
中 移动(结果);
}
私:
文系::路径 路径;
串 结果;
};
任务<大小型>读文件(){
输出<<本线程::取标识()<<"读文件():将异步读文件";
常 动 结果=协待 异步读文件{"../主.c++"};
输出<<本线程::取标识()<<"读文件():将中(大小"
<<结果.大小()<<")\n";
协中 结果.大小();
}
整 主(){
动 任务=读文件();
本线程::休息(1s);
输出<<"文件大小="<<任务.取结果()<<'\n';
}
写了异步读文件
的等待器
,通过协待
挂起协程
并等待线程完成读文件
,当读完成
后恢复挂起
的协程,得到读到的文件长度
.
注意:这里在止挂起
时,返回了止等待器
来恢复之前等待异步读
而挂起的协程
,从而获得等待器
的返回值
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现