Coroutine


  • 头文件中的定义

    • 为协程定义了四种状态

      1. 挂掉的协程

      2. 就绪的协程

      3. 运行中的协程

      4. 挂起的协程

    • 协程表的结构体

    • 定义协程可控函数

    • 协程操作函数

      • coroutine_open 返回一个初始化完成的协程表

      • coroutine_close 传入协程表,关闭协程

    • 协程表操作函数

      • 添加一个协程到协程表中 需要一下参数

        • 协程表结构体,协程函数,协程参数

      • 恢复一个协程

      • 返回一个协程的状态

      • 选择一个协程运行

      • 让出当前协程的控制权

  • 查看头文件中函数的使用,之后再看定义

  • 抽象数据类型解析

    • 协程调度表

      • 栈大小 1MB

      • 主线程的上下文

      • 当前协程数

      • 协程容量

      • 正在执行的协程的id

      • 协程数组

       


    • 协程

      • 协程函数

      • 函数参数

      • 当前协程上下文

      • 协程调度器

      • 已分配内存

      • 协程状态

      • 运行时栈


  • 协程函数

    • 协程的初始化函数和删除函数[该函数时是static的被封装起来,属于调度器的私有函数](没有考虑信号,重启函数,应该使用,或者考虑可重入机制)这个只是一个想法 考虑异常控制流 协程结合IO多路复用epoll

    • 调度器函数

      • 返回一个协程调度器 ,默认最大协程数位16 ,并创建和初始化协程数组

      • 调用内部函数释放所有协程

    • 将新协程添加到调度表中

      • 如果当前协程数超过最大协程数进行两倍扩容

      • 如果成功就返回 当前协程的id

      • 失败返回-1

    • 编写协程函数执行函数

      • 通过或运算组合高低32bit地址,组合位调度表(基于兼容性的考虑,才采用了这种做法)

      • 恢复协程

        • 判断函数状态

        • 执行相应的函数

          • 如果时READY 则变换到 运行态 运行后 切换到主线程

          • 原本挂起的函数 则执行一个恢复上下文

        • 让出协程

          • 保存当前协程上下文,恢复到主线程

          • 保存线程时传入的时调度表的栈基础地址

        • 保存栈

          • 用栈机制得到当前栈大小 ,因为新变量需要取地址,所以会在栈上开辟空间,我们得到了栈的大小

          • 将栈数据拷贝回协程栈

          • 这里使用的是共享栈,增加了拷贝,节约了空间

        • 以上操作,需要知道这些

          • 保存一个函数栈的上下文,

            • 函数维护的数据

              • 函数的PC寄存器,段寄存器(ESP),以及调用者保存的寄存器,被调用者保存的寄存器

              • 不是存储在寄存器中的数据

              • 一个函数栈[rbp, ebx, 局部变量,参数构造器],我们默认使用pure function即没有副作用的函数

         

         



    可不可以把每个函数连续存放,看做一个函数数组,通过id操作某个部分,虽然可能安全性不高,但是,应该是可行的,每次数组某个位置执行完成,保存函数,暂时还没啥思路。