彻底了解C++异步从理论到实践

本文探讨了C++异步编程,特别是结合c++20 coroutine和asio库的使用。文章首先介绍了游戏框架异步设计的背景,然后详细讲解了asio库中的executor、strand和timer任务,并对比了asio与其他异步实现。文中还提到了libunifex库的优缺点,以及如何在实践中结合asio和execution概念。最后,文章讨论了如何重新思考异步框架的设计,提出了一些解决方案和示例代码。
摘要由CSDN通过智能技术生成

1. 纠结的开篇

之前设计我们游戏用的c++框架的时候, 刚好c++20的coroutine已经发布, 又因为是专门 给game server用的c++ framework, 对多线程的诉求相对有限, 或者本着少并发少奇怪的错误的原则, 除网络和IO和日志等少量模块外, 大部分模块主要还是工作在主线程上的, 所以当时设计的重点也就放在了c++20 coroutine的包装和使用上, 更多的使用coroutine来完善异步的支持. 但如果考虑到framework作为前后端公用框架的话, 原来主要针对主线程使用的包装的coroutine调度器就显得有些不够用, 以此作为基础, 我们开始了尝试结合比较新的c++异步思路, 来重新思考应该如何实现一个尽量利用c++新特性, 业务层简单易用的异步框架了.

本系列的主要内容也是围绕这条主线来铺开, 过程中我们 主要以:

  1. 自有的framework异步实现 - 主要落地尝试利用c++20的coroutine实现一个业务级的调度器.

  2. asio - 这个应该不用多说了, 近年来一直高频迭代, 业界广泛使用的开源第三方库, 中间的异步任务调度, 网络部分的代码实现都非常优质.

  3. libunifex - 最接近当前sender/receiver版 execution提案的可实操版本, c++17/20兼容, 但不推荐使用c++17的版本进行任何尝试, 原因后续文件会展开. 这几个库作为基础, 逐步展开我们对c++异步的探索, 然后再回到落地实践这条主线上, 探讨一个业务侧使用简单, 内部高效的异步库应该如何来实现并落地. 当然, 我们的侧重点主要还是c++异步的调度和处理上, 网络相关的有部分内容可能会简单提到, 但不会进行深入的展开.   其实整个尝试的过程只能说非常不顺利了, 当然, 随着对相关实现的深入理解和细节的深挖, 收益也是颇多的. 闲话不多说了, 我们直接切入主题, 以对异步的思考来展开这篇总览的内容.

2. 前尘往事 - rstudio framework实现

rstudio framework的异步框架由两块比较独立的部分组成:

  1. 一部分是源自asio几年前版本的post和strand部分实现, 另外附加了一些业务侧较常用的像Fence等对象;

  2. 另外一部分是主线程的协程调度器实现, 这部分最早是基于c++17实现的一版stackless 协程; 另外一版则是gcc11.1正式发布后, 直接用c++20重构了整个实现, 直接使用c++20的coroutine的一个版本.

2.1 asio 部分

  这一部分的内容因为后续有asio scheduler实现具体的分析篇章, 这个地方主要以业务侧使用进行展开了.

2.1.1 executor概述

  • 来源于1.6X boost同期的asio standalone版本

  • 去除了各平台网络处理相关的代码

  • 仅保留了post和相关的功能(新版本有executor实现)

  • 早期c++11兼容, 无coroutine支持

  • 除网络库外, asio非常有使用价值的一部分代码

2.1.2 一个简单的使用示例

  GJobSystem->Post([]() {
        //some calculate task here
        //...
        GJobSystem->Post(
            []() {
                //task notify code here
                //...
            },
            rstudio::JobSystemType::kLogicJob);
      }, rstudio::JobSystemType::kWorkJob);

相关的时序图:

2.1.3 当前框架使用的线程结构

​预定义的枚举值:

enum class JobSystemType : int {
  kLogicJob = 0,       // logic thread(main thread)
  kWorkJob,            // work thread
  kSlowJob,            // slow work thread(run io or other slow job)
  kNetworkJob,         // add a separate thread for network
  kNetworkConnectJob,  // extra connect thread for network
  kLogJob,             // log thread
  kNotifyExternalJob,  // use external process to report something, 1 thread only~~
  kTotalJobTypes,
};

不同Job说明:

  • kLogicJob

  • 主线程(逻辑线程)执行任务

  • kWorkJob

  • Work Thread线程池执行任务(多个), 一般是计算量可控的小任务

  • kSlowJob

  • IO专用线程池, IO相关的任务投递到本线程池

  • kNetworkJob

  • 目前tbuspp专用的处理线程

  • kNetworkConnectJob

  • 专用的网络连接线程, tbuspp模式下不需要

  • kLogJob

  • 日志专用线程, 目前日志模块是自己起的线程, 可以归并到此处管理

  • kNotifyExternalJob

  • 专用的通知线程, 如lua error的上报, 使用该类型

【文章福利】另外小编还整理了一些C++后台开发面试题,教学视频,后端学习路线图免费分享,需要的可以自行添加:学习交流群点击加入~ 群文件共享

小编强力推荐C++后台开发免费学

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值