上下文简介

首先要理解boost::context的概念和应用场景。程序在执行的时候,当前的执行的代码环境和所处的状态,就是context。boost::context保留了当前程序执行时的寄存器等的状态,可以认为是一个上下文A;然后线程就可以去执行其他的代码,完成执行后,可以切回上下文A,并从当初切走的地方执行,而且当初的上下文的现场不变,这就是完成了一次真正意义上的上下文切换。

上线文切换,在协程和用户态线程等有重要的意义(统称它们为routine),我们可以启动一定数量的操作系统的线程,然后让routine在OS的thread中切换,切换时仅需要保留有关的上下文即可,通过一定的调度方式,是的OS的Thread不停的执行这些routine。routine的切换速度,远远快于thread,可极大提高效率。

boost::context提供了上下文的抽象,并给了两种方式,fibercall/cc的方式保留和执行上下文切换。分别介绍两种模式。

fiber的方式切换上下文

fiber是指,在fiber之后的代码片段,比如:

boost::context::fiber f{// your code
}

其中your code就是fiber的内容,是一个特殊格式的函数。当执行上下文时,会进行有关的调用。

int main() {namespace ctx = boost::context;int genNum{0};bool stop{false};// 初始化fiber,sink是启动该上下文的调用者的fiber,该实例中是指main的上下文ctx::fiber generator{[&genNum, &stop](ctx::fiber &&sink) {  while (true) {if (stop) {break;}genNum = (genNum + 1) * 2;sink = std::move(sink).resume(); // 保留当前routine的状态,切回到调用者的上下文状态,resume表示执行}return std::move(sink); // 必须返回调用者的上下文状态}};genNum = 1;for (int i = 0; i < 10; ++i) {generator = std::move(generator).resume(); // 切换到generator的上下文并执行std::cout << genNum << " ";}std::cout << std::endl;return 0;
}

编译:

g++ main.cpp -o main -g -std=c++17 -lpthread -lboost_fiber -lboost_context && ./main

最终输出:

4 10 22 46 94 190 382 766 1534 3070

注意几个关键点:

  • routine的调用,是在一个线程中的,因此同一个线程中的routine,不可以出现任何线程锁
  • fiber只有移动语义,没有构造语义
  • resume()resume_with()函数只能右值调用,因此需要使用std::move把左值转换成右值。使用右值,是为了表示恢复fiber之后,原来的fiber就无效了。

给出一个更加经典的生产者和消费者的例子,代码示例:

void pro_con(int N) {namespace ctx = boost::context;std::queue<int> buffer;bool stop = false; // 消除IDE报警用// 生产者ctx::fiber producer{[&buffer, &stop](ctx::fiber &&sink) {int cargo = 0;for (;;) {if (stop) {break;}buffer.push(cargo);std::cout << "producer push " << cargo << std::endl;++cargo;sink = std::move(sink).resume(); // 移交控制权}return std::move(sink);}};// 消费者ctx::fiber consumer{[&buffer, &stop](ctx::fiber &&sink) {for (;;) {if (stop) {break;}int n = buffer.front();buffer.pop();std::cout << "consumer pop " << n << std::endl;sink = std::move(sink).resume(); // 移交控制权}return std::move(sink);}};for (int i = 0; i < N; ++i) {producer = std::move(producer).resume();consumer = std::move(consumer).resume();}
}int main() {pro_con(10);return 0;
}

resume_with可以在resume之前,添加一个新的上下文,比如上面消费者的代码改成:

    // 消费者ctx::fiber consumer{[&buffer, &stop](ctx::fiber &&sink) {for (;;) {if (stop) {break;}int n = buffer.front();buffer.pop();std::cout << "consumer pop " << n << std::endl;sink = std::move(sink).resume_with([](ctx::fiber &&f) {std::cout << "====" << std::endl;return std::move(f);}); // 移交控制权}return std::move(sink);}};

这样,会输出如下的形式:

producer push 0
consumer pop 0
====
producer push 1
consumer pop 1
====

callcc方式切换上下文

该方式和fiber的调用基本一致,这里给出代码实例即可:


int main() {namespace ctx=boost::context;int a;bool stop = false;ctx::continuation source = ctx::callcc([&a, &stop](ctx::continuation &&sink) {a = 0;int b = 1;for (;;) {if (stop) {break;}sink = sink.resume();int next = a + b;a = b;b = next;}return std::move(sink);});for (int j = 0; j < 10; ++j) {std::cout << a << " ";source = source.resume();}return 0;
}

boost context上下文切换相关推荐

  1. 协程分析之 context 上下文切换

    转载:https://juejin.im/entry/6844903448849154061 协程现在已经不是个新东西了,很多语言都提供了原生支持,也有很多开源的库也提供了协程支持. 最近为了要给tb ...

  2. Boost::context模块fiber的throw测试程序

    Boost::context模块fiber的throw测试程序 实现功能 C++实现代码 实现功能 Boost::context模块fiber的throw测试程序 C++实现代码 #include & ...

  3. Boost::context模块fiber的stack测试程序

    Boost::context模块fiber的stack测试程序 实现功能 C++实现代码 实现功能 Boost::context模块fiber的stack测试程序 C++实现代码 #include & ...

  4. Boost::context模块fiber的分段的测试程序

    Boost::context模块fiber的分段的测试程序 实现功能 C++实现代码 实现功能 Boost::context模块fiber的分段的测试程序 C++实现代码 #include <c ...

  5. Boost::context模块fiber的解析器测试程序

    Boost::context模块fiber的解析器测试程序 实现功能 C++实现代码 实现功能 Boost::context模块fiber的解析器测试程序 C++实现代码 #include <c ...

  6. Boost::context模块fiber的jump_void测试程序

    Boost::context模块fiber的jump_void测试程序 实现功能 C++实现代码 实现功能 Boost::context模块fiber的jump_void测试程序 C++实现代码 #i ...

  7. Boost::context模块fiber的jump_mov测试程序

    Boost::context模块fiber的jump_mov测试程序 实现功能 C++实现代码 实现功能 Boost::context模块fiber的jump_mov测试程序 C++实现代码 #inc ...

  8. Boost::context模块fiber的jump测试程序

    Boost::context模块fiber的jump测试程序 实现功能 C++实现代码 实现功能 Boost::context模块fiber的jump测试程序 C++实现代码 #include < ...

  9. Boost::context模块fiber的斐波那契测试程序

    Boost::context模块fiber的斐波那契测试程序 实现功能 C++实现代码 实现功能 Boost::context模块fiber的斐波那契测试程序 C++实现代码 #include < ...

最新文章

  1. 拼多多再起波澜!某程序员匿名发布拼多多楼下救护车照片,却被揪出开除!...
  2. 老男孩python21期作业_(禁闲聊)绘画讨论10个群第176期作业展示
  3. 读写文件、文件方法、python2的乱码问题、python对passwd文件进行排序
  4. mysql报错1517_请教一下 flask+sqlalchemy+mysql 连接错误问题
  5. iphone three20 保存本地的图片
  6. Win10 安装 Linux 子系统
  7. Flex中如何通过设置GridLines对象的horizontalAlternateFill样式交错显示LineSeries图表背景颜色的例子...
  8. 【 Codeforces Round #551 (Div. 2) D】Serval and Rooted Tree【树形DP】
  9. 在中标麒麟上基于源码安装第二个gcc编译器
  10. android 解压zip工具,ZArchiver解压缩工具
  11. 气体流量与质量流率换算
  12. 【方向盘】达到Linux第三阶段的常用命令笔记记录---PartⅠ
  13. 微信小程序地图篇(腾讯地图)
  14. AppCompatActivity透明化处理
  15. 助你掌握搜索神器,10个实用的Elasticsearch查询技巧
  16. 集成seata到springboot,cloud项目,找不到事务分组
  17. 2.2 数据的表示和存储(二)
  18. 嵌入式系统开发09——串口通信
  19. 【环境部署】华为云ECS安装MySQL
  20. windows系统安装jdk11

热门文章

  1. php js后端渲染,webpack后端渲染详解
  2. java 开发环境配置文件_Java 开发环境配置
  3. A-Night at the Museum 水题
  4. python网络爬虫学习笔记(八):XPath的使用
  5. 荷兰国旗问题(三元素数组排序问题)
  6. LeetCode 76. 最小覆盖子串 (滑动窗口哈希表)
  7. java中基本数据类型
  8. Intellij idea控制台中文乱码问题
  9. CSDN 勤写标兵勋章 颁发规则
  10. Calendar类和GregorianCalendar类