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

这篇具有很好参考价值的文章主要介绍了TBB库中实现协程(coroutine)的源码说明。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

源码请见: 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)调度示意图,如下图所示

TBB库中实现协程(coroutine)的源码说明,c++/c/asm,windows,c++

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纤程的协程实现,这个实现要复杂一些。文章来源地址https://www.toymoban.com/news/detail-627536.html

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);
}

到了这里,关于TBB库中实现协程(coroutine)的源码说明的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【unity知识点】Unity 协程Coroutine

    Unity 协程是一种特殊的函数,可以在游戏中实现延迟执行、按顺序执行和异步操作等功能。它使用了迭代器(Iterator)的概念,通过 yield 来控制执行流程。下面是 Unity 协程的使用和使用场景的详细介绍。 在脚本中定义一个协程方法,返回值类型为 IEnumerator 。 在协程方

    2024年02月01日
    浏览(38)
  • Kotlin 协程库v1.7.1的核心模块(kotlinx-coroutines-core)-- kotlinx.coroutines篇

    目录 asContextElement: asCoroutineDispatcher: js asDeferred: asExecutor: js asPromise: async: js await: awaitAll: awaitCancellation: cancelAndJoin: cancelChildren: CancellableContinuation: CancellationException: CloseableCoroutineDispatcher: CompletableDeferred: CompletableJob:  completeWith:  CompletionHandler: CoroutineDis

    2024年02月03日
    浏览(43)
  • UE4/5C++多线程插件制作(十六、Coroutines协程封装)

    目录 准备 MTPCoroutines.h MTPCoroutines.cpp 我们要对协程继续封装制作: 协程是一种计算机程序组件,它允许在某个位置暂停执行,然后在稍后的时间点恢复执行。与传统的函数调用不同,协程可以被多次调用并且能够保留其内部状态,从而允许程序在执行到一定点时暂停,执行其

    2024年02月15日
    浏览(48)
  • 关于 Go 协同程序(Coroutines 协程)、Go 汇编及一些注意事项。

    参考:  Go 汇编函数 - Go 语言高级编程 Go 嵌套汇编 - 掘金 (juejin.cn) 前言: Golang 适用 Go-Runtime(Go 运行时,嵌入在被编译的PE可执行文件之中)来管理调度协同程式的运行。 Go 语言没有多线程(MT)的概念,在 Go 语言之中,每个 Go 协程就类似开辟了一个新的线程,效率上,肯

    2024年01月25日
    浏览(71)
  • 06.2_c/c++开源库boost_coroutine2 协程库

    sudo apt install libboost-coroutine1.71-dev libboost-coroutine不支持.pc格式查看, 支持.cmake导入 cat /usr/lib/x86_64-linux-gnu/cmake/boost_coroutine-1.71.0/boost_coroutine-config.cmake cat /usr/lib/x86_64-linux-gnu/cmake/boost_coroutine-1.71.0/libboost_coroutine-variant-shared.cmake 可知依赖: atomic chrono context thread 从安装路径可知 头

    2024年04月28日
    浏览(40)
  • Vue中实现图片懒加载简单说明

    npm i vue-lazyload@1.2.6 import VueLazyload from \\\"vue-lazyload\\\"; 说明:main.js文件 说明:vue文件    

    2024年02月13日
    浏览(39)
  • Kotlin协程的JVM实现源码分析(上)

    本文从协程的启动 launch 源码入手分析,协程JVM实现分为两篇: 协程启动和执行源码分析 无栈协程 和 Continuation 基本环境: IntelliJ IDEA 2023.3.2 Kotlin 1.8.20 kotlinx-coroutines-core 1.7.3 gradle 8.2 以 GlobalScope.launch 启动协程分析: 调用关系: CoroutineScope.launch - StandaloneCoroutine.start - Corou

    2024年01月19日
    浏览(39)
  • Kotlin协程的JVM实现源码分析(下)

    协程 根据 是否保存切换 调用栈 ,分为: 有栈协程(stackful coroutine) 无栈协程(stackless coroutine) 在代码上的区别是:是否可在普通函数里调用,并暂停其执行。 Kotlin协程,必须在挂起函数中调用和恢复,属于 无栈协程 。 常见的语言,协程实现: 有栈协程 :Go、Lua 无栈

    2024年01月23日
    浏览(45)
  • [学习分享]----sylar服务器框架源码阅读--IO协程调度模块

    sylar作者在本站的地址为 这里,也可以查看 作者主页,也有视频教程可以 点击这里。此外,也可以看一下赵路强大佬的关于sylar协程模块的博客 点击这里,我本人在阅读sylar源码的时候也是参考了赵路强大佬的解析 可以点击这里。 各位看官也可以加我的qq和我讨论2511010742

    2024年01月17日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包