TBB库中实现协程(coroutine)的源码说明

news2024/11/23 13:04:26

源码请见: https://github.com/oneapi-src/oneTBB/blob/master/src/tbb/co_context.h

在windows系统,TBB(也就是intel 的 oneTBB库),通过windwos fiber(纤程)来实现协程(coroutine)。

创建一个协程,代码很简洁:

inline void create_coroutine(coroutine_type& c, std::size_t stack_size, void* arg) {
    __TBB_ASSERT(arg, nullptr);
    c = CreateFiber(stack_size, co_local_wait_for_all, arg);
    __TBB_ASSERT(c, nullptr);
}

windows系统中线程(thread)与纤程(fiber)调度示意图,如下图所示

windwos中的纤程和通常说的协程类似,处在用户模式下,和内核态无关不会有切换复杂上下文的开销。一个线程一次只能执行一个纤程,实际单个线程上的上多纤程利用时间片形成并发机制。进程与线程是内核态相关的操作机制,调度过程是抢占式的。而协程调度是在用户态完成的,需要代码里显式地将CPU调度交给其他协程,这是协作式的。

在不考量多核心cpu算力扩展的情况下,只谈调度效率或者一个程序对单个cpu的利用率,协程要高效得多。而且,本质上来说,一个线程里面的协程是没有并行机制里面的数据竞争的,这意味着保证同步正确性(没有数据竞争问题)的同时具有了异步灵活性。

将 CPU 的执行从一个线程切换到另一个线程,不可避免地涉及内核调度机制,这是个昂贵的开销操作,如果两个线程经常频繁地来回切换则代价尤其大。 Windows 实现了两种机制来降低这一开销:纤程(fiber)和用户模式调度(UMS , user-mode scheduling)。
纤程使得一个应用程序可以调度它自己的“线程”的执行过程,而不必依赖于 Windows 内置的基于优先级的调度机制。纤程也常被称为“轻量”线程:从调度的角度来看,它们对于内核是不可见的,因为它们是在用户模式下在 Kemel32.dll 中实现的。为了使用纤程,首先要调用 Windows 的 ConvertThreadToFiber 函数。该函数将当前线程转变成一个正在运行的纤程。之后,在转变得到的纤程中,通过调用 CreateFiber 函数,又可以创建额外的纤程(每个纤程可以有它自己的一组纤程)。然而,与线程不同的是,纤程不会自动执行,它必须由 SwitchToFiber 函数手工选中,然后才能执行。新的纤程会一直运行,直到退出,或者调用SwitchToFiber再次选择运行另一个纤程。

感谢: https://www.cnblogs.com/5iedu/p/4830983.html

在linux系统下使用glibc中的ucontext库实现,比起基于windows纤程的协程实现,这个实现要复杂一些。

inline void create_coroutine(coroutine_type& c, std::size_t stack_size, void* arg) {
    const std::size_t REG_PAGE_SIZE = governor::default_page_size();
    const std::size_t page_aligned_stack_size = (stack_size + (REG_PAGE_SIZE - 1)) & ~(REG_PAGE_SIZE - 1);
    const std::size_t protected_stack_size = page_aligned_stack_size + 2 * REG_PAGE_SIZE;

    // Allocate the stack with protection property
    std::uintptr_t stack_ptr = (std::uintptr_t)mmap(nullptr, protected_stack_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
    __TBB_ASSERT((void*)stack_ptr != MAP_FAILED, nullptr);

    // Allow read write on our stack (guarded pages are still protected)
    int err = mprotect((void*)(stack_ptr + REG_PAGE_SIZE), page_aligned_stack_size, PROT_READ | PROT_WRITE);
    __TBB_ASSERT_EX(!err, nullptr);

    // Remember the stack state
    c.my_stack = (void*)(stack_ptr + REG_PAGE_SIZE);
    c.my_stack_size = page_aligned_stack_size;

    err = getcontext(&c.my_context);
    __TBB_ASSERT_EX(!err, nullptr);

    c.my_context.uc_link = nullptr;
    // cast to char* to disable FreeBSD clang-3.4.1 'incompatible type' error
    c.my_context.uc_stack.ss_sp = (char*)c.my_stack;
    c.my_context.uc_stack.ss_size = c.my_stack_size;
    c.my_context.uc_stack.ss_flags = 0;

    typedef void(*coroutine_func_t)();

    std::uintptr_t addr = std::uintptr_t(arg);
    unsigned lo = unsigned(addr);
    unsigned hi = unsigned(std::uint64_t(addr) >> 32);
    __TBB_ASSERT(sizeof(addr) == 8 || hi == 0, nullptr);

    makecontext(&c.my_context, (coroutine_func_t)co_local_wait_for_all, 2, hi, lo);
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker【安装、存储、镜像、仓库、网络、监控】

docker-0110.0.0.51docker-0210.0.0.52docker-0310.0.0.53 【1】docker安装 docker-01 [rootdocker-01 ~]# vim /etc/yum.conf [main] cachedir/var/cache/yum/$basearch/$releasever keepcache1 debuglevel2 logfile/var/log/yum.log exactarch1 obsoletes1 gpgcheck1 plugin…

安防监控视频融合EasyCVR平台接入RTSP流后设备显示离线是什么原因?

安防监控视频EasyCVR视频汇聚融合平台基于云边端智能协同架构,具有强大的数据接入、处理及分发能力,平台支持海量视频汇聚管理、全网分发、按需调阅、鉴权播放、智能分析等视频能力与服务。平台开放度高、兼容性强、可支持灵活拓展与第三方集成&#xff…

GO学习之 函数(Function)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 文章目录 GO系列前言一、什么是函数?二、函数声明…

vue响应数据为二维码如何渲染到页面

在postman测试请求后发现响应数据为一个二维码图片,不是链接,如何解决? 然后如果在vue中使用请求还会报Uncaught (in promise) SyntaxError: Unexpected token o in JSON at position 1的错误。这个就是使用了JSON.parse导致的响应格式不对),使用JSON.stringify解决…

<dependency> idea中为什么这个变黄色

在IDE中&#xff0c;当你的代码出现黄色高亮时&#xff0c;通常表示存在警告或建议的提示。对于Maven的<dependency>标签来说&#xff0c;黄色高亮可能有以下几种原因&#xff1a; 依赖项未找到&#xff1a;黄色高亮可能表示IDE无法找到指定的依赖项。这可能是由于配置错…

【前端】鼠标事件计算与圆心形成的角度

在业务需求中&#xff0c;常常出现一些我们无法完成的效果图&#xff0c;这时需要UI切图给我们&#xff0c;而切图后不可避免的一些点击事件无法方便的监听 如该图圆环&#xff0c;其实是一张单独的图片&#xff0c;这种情况下只能通过js判断用户点击、拖动的鼠标位置&#xf…

【Python】基础:OpenCV库基本应用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍OpenCV库基本应用。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&…

【项目 计网1】4.1 网络结构模式 4.2MAC地址、IP地址、端口

文章目录 第四章 Linux网络编程4.1 网络结构模式C/S结构&#xff08;client-server&#xff09;B/S结构&#xff08;Browser/Server&#xff0c;浏览器/服务器模式&#xff09; 4.2 4.3MAC地址、IP地址、端口&#xff08;1&#xff09;&#xff08;2&#xff09;MAC地址IP地址(…

abp vnext升级到指定版本并处理升级后的问题

在使用abp vnext时当版本更新后可能会跨越net的版本&#xff0c;如果我们想升级到指定版本该怎么做呢&#xff0c;升级之后又有一些问题需要处理&#xff0c;下面一起看一下&#xff1a; 当前我的项目是.net5 abp vnext4.2.1 当前的最新abp版本是7.* 对应的net版本是 net7,由于…

FFmpeg常见命令行(二):FFmpeg转封装

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》。本文是Android音视频任务列表的其中一个&#xff0c; 对应的要学习的内容是&#xff1a;如何使…

【Verilog/D8】

2023年8月5日 HDBits/Cs450/counter 2bc状态机异步复位noteHDBits/Cs450/history shiftHDBits/Cs450/gshare HDBits/Cs450/counter 2bc状态机 Cs450/counter 2bc LSB最低有效位 module top_module(input clk,input areset,input train_valid,input train_taken,output reg[1…

选读SQL经典实例笔记18_Exactly

1. 问题9 1.1. 只讲授一门课程的教授 1.2. sql select p.*from professor p,teach twhere p.lname t.lnameand p.lname not in ( select t1.lnamefrom teach t1,teach t2where t1.lname t2.lnameand t1.cno &#xff1e; t2.cno ) LNAME DEPT SALARY …

抖音seo矩阵系统源代码开发搭建技术分享

抖音SEO矩阵系统是一个较为复杂的系统&#xff0c;其开发和搭建需要掌握一定的技术。以下是一些技术分享&#xff1a; 技术分享 抖音SEO矩阵系统的源代码可以使用JAVA、Python、PHP等多种语言进行开发。其中&#xff0c;JAVA语言的应用较为广泛&#xff0c;因为JAVA语言有良好…

运输层---UDP协议

目录 一. 无连接运输&#xff1a;UDP1.1 定义1.2 特点1.3 应用 二. UDP报文段结构三. UDP检验和3.1 定义3.2 检验和计算实例3.2 UDP检验和的局限 一. 无连接运输&#xff1a;UDP 1.1 定义 UDP&#xff08;User Datagram Protocol&#xff09;用户数据报协议&#xff1a;由 [RF…

数字图像处理 使用 GIST 图像描述符

一、简述 GIST描述符是一种用于场景识别的全局图像特征,它能够有效地描述图像的空间结构信息。GIST描述符最初是在这篇论文中提出的:A Computational Approach to Edge Detection 1998。 图像的 GIST 描述符可以通过分析空间频率和方向来捕获。直观上,GIST 总结了图像不同部分…

九、pig安装

1.上传pig包 2.解压文件 3.改名 4.赋权 5.配置环境变量 export PIG_HOME/usr/local/pig export PATH$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HIVE_HOME/bin:$HBASE_HOME/bin:$SQOOP_HOME/bin:$PIG_HOME/bin 6.测试

ensp-DHCP服务实验

ensp-DHCP服务实验 日期&#xff1a;6-26 &#x1f4ce;DHCP服务器.zip&#x1f4ce;dhcp服务作业.docx

剑指 Offer 50. 第一个只出现一次的字符

题目描述 在字符串 s 中找出第一个只出现一次的字符。如果没有&#xff0c;返回一个单空格。 s 只包含小写字母。 示例 思路1 如果一个字符首次出现indexOf和最后一次出现lastIndexOf的位置相同&#xff0c;说明只出现了一次 从左到右遍历即可得到第一个不重复出现的数字cla…

c++11 标准模板(STL)(std::basic_ofstream)(三)

定义于头文件 <fstream> template< class CharT, class Traits std::char_traits<CharT> > class basic_ofstream : public std::basic_ostream<CharT, Traits> 类模板 basic_ifstream 实现文件流上的高层输入操作。它将 std::basic_istrea…

DLA 神经网络的极限训练方法:gradient checkpointing

gradient checkpointing 一般来说&#xff0c;训练的过程需要保存中间结果&#xff08;不管是GPU还是CPU&#xff09;。前向传播根据输入(bottom_data)计算输出(top_data)&#xff0c;后向传播由top_diff计算bottom_diff&#xff08;如果某个变量打开梯度进行训练的话&#xff…