现代 C++20 实战高手课
卢誉声
Autodesk 首席工程师
3781 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 29 讲
现代 C++20 实战高手课
15
15
1.0x
00:00/00:00
登录|注册

10|Coroutines实战(二):异步文件操作库

你好,我是卢誉声。
今天,我们继续上一讲的工作,实现基于协程调度的异步文件系统操作库。同时,在这一讲中,我们还要探讨一个重要话题,即实现所有调度线程全异步化的理想异步模型。
上一讲的最后,我们已经实现了任务调度模块,这意味着我们搭建好了基于协程的任务调度框架。但是,目前 task 模块是运行在主线程上的。因此,只有当主线程没有其他任务执行时,task 模块才会从消息循环中获取任务执行,并唤醒协程。
这不是一个理想的异步框架模型,我们更希望实现的是主线程和 I/O 调度全异步化。那么,这要如何实现呢?
项目的完整代码,你可以这里获取。

I/O 调度模块

其实,task 模块中预留的 AsyncTaskSuspender 函数,就是为了实现自定义任务的处理与唤醒机制。为此,我们继续讨论异步 I/O 的实现——基于 task 模块的任务调度框架,实现基于协程的异步 I/O 调度。
我们的基本思路是下图这样。
首先,我们要为 I/O 任务创建独立的任务队列。然后,AsyncTaskSuspender 中的主线程,负责将任务与协程的唤醒函数分发到 I/O 任务队列中。
接下来还要创建一个有独立任务循环的新线程,读取 I/O 任务队列,用于处理 I/O 任务。最后,处理完 I/O 任务后,将任务的返回值和协程唤醒函数分发到主线程的任务队列中。根据主线程的任务循环机制,当主线程空闲时,唤醒协程。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了如何使用协程实现异步文件操作库,并探讨了实现所有调度线程全异步化的理想异步模型。文章首先介绍了基于协程调度的异步文件系统操作库的实现思路,包括创建独立的I/O任务队列和使用新线程处理I/O任务。接着,详细介绍了task分区、loop分区和asyncify分区的具体实现,展示了如何实现异步I/O的处理流程。通过对代码的解析,读者可以了解如何使用协程实现异步I/O任务处理的细节,以及如何将普通函数转换成支持在协程中异步执行的函数。此外,文章还简要介绍了文件系统操作模块的封装方法,展示了如何使用ioAsyncify将普通函数转换成异步任务函数。整体而言,本文通过具体的代码实现和解析,帮助读者快速了解了使用协程实现异步文件操作库的技术特点。文章还深入讨论了C++ Coroutines的概念,包括协程调度的细节和实现约定,为读者提供了更深入的理解。最后,文章指出了C++ Coroutines的潜力和未来发展前景,展望了在未来C++标准中对协程的更加成熟的支持。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《现代 C++20 实战高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(2)

  • 最新
  • 精选
  • 猪小擎
    老师的github代码有好多GBK文件,建议修改下。 携程的本质优点减少上下文切换,(中断),中断操作系统会把寄存器存在栈顶,然后内核栈和用户栈互换,这些大概会消耗1-10微秒。携程就要节约这无数的1-10微秒。可以操作系统的IO操作是默认会中断的,要把中断改成yield出让执行权需要做什么呢?底层调用的filesystem的操作本身就是中断操作吧?上层改成携程,对于进程来说,这中断的消耗并没有节省。

    作者回复: 感谢反馈,源代码正在做更新。 这里我们协程是一个简单的“示例性”封装,实际要通过协程处理I/O肯定要以IOCP、epoll和kqueue等技术为基础,并利用协程作为接口封装,在避免多线程与锁的情况下实现任务上下文切换,而不是直接使用filesystem这种简单的同步I/O接口,但是如果这样就会偏离我们想要讲解的重点,所以就使用filesystem做了简单的示例。

    2023-03-30归属地:北京
    2
    1
  • peter
    请教老师两个问题: Q1:asyncF与testVoid定义为什么不同? asyncF与testVoid都是协程,但testVoid的定义是:asyncpp::task::Coroutine testVoid();而testVoid的定义是Coroutine asyncF()。函数前面部分不同,为什么? Q2:协程在C++语法层面的支持就是几个关键字吗? 这两篇读下来,有点模模糊糊,总体上感觉在C++语法层面,对于协程,似乎就是Coroutine、co_await这两个关键字,是吗?(Awaitable 和 Awaiter需要自己实现,不算关键字吧)

    作者回复: Q1: 代码前面已经using asyncpp::task::Coroutine,所以这里asyncpp::task::Coroutine和Coroutine是一样的,这里只是演示引用该类型的不同用法,没有其他不同。 Q2:C++的协程提供了: (1)关键字:协程只提供了co_await、co_yield这两个关键字。 (2)基础类型支持:coroutine_handle是C++协程标准库内提供的类型 (3)协程协议框架:其他部分只定义了一个协议框架,包括Coroutine、Promise、Awaitable和Awaiter都是标准提出的概念,并且定义了相关的标准协议,但是并没有提供标准实现或者工具,需要开发者熟悉这些协议然后自己实现。 所以说,就目前来说(在C++26或后续标准到来以前)实现一个C++20的协程框架确实并不容易,但是基于框架再做业务开发就会简单很多。

    2023-02-07归属地:北京
收起评论
显示
设置
留言
2
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部