cocore 阅读

image.png

1: coobjc.h 内联函数 启动协程

co_launch(^{

});

2.将block转换成OC协程对象 COCoroutine.m 并且创建c的协程对象coroutine_t

        COCoroutine *co = [COCoroutine coroutineWithBlock:block onQueue:nil];

        coroutine_t  *co = coroutine_create((void (*)(void *))co_exec);
        if (stackSize > 0 && stackSize < 1024*1024) {   // Max 1M
            co->stack_size = (uint32_t)((stackSize % 16384 > 0) ? ((stackSize/16384 + 1) * 16384) : stackSize);        // Align with 16kb
        }
        //设置  coroutine_t 为当前COCoroutine属性 _co
        //c协程对象 coroutine_t 和 当前 OC对象 COCoroutine 双向引用
        _co = co;
        coroutine_setuserdata(co, (__bridge_retained void *)self, co_obj_dispose);
        //将OC绑定到couserdata
        co->userdata = userdata;
        //设置释放回调指针
        co->userdata_dispose = ud_dispose;

3. 执行协程 coobjc.h COCoroutine.m

return [co resume]; 
//将当前任务放入CODispatch 队列
3.1 self.dispatch dispatch_async_block:^{
        //将协程添加到调度程序 进入真正的协程处理方法
        //跳转到 coroutine_resume_im.m
        coroutine_resume(self.co);
    }];
3.1 //获取当前运行的协程
    coroutine_t *coroutine_self() 
3.2 //获取当前运行的协程调度器。调度器跟协程关系?
    // 调度器由一个主协程,co->is_scheduler = true;
    // 调度器结构
        struct coroutine_scheduler {
            coroutine_t         *main_coroutine; //跟随调度器同时生成的主协程
            coroutine_t         *running_coroutine; //当前正在运行的协程
            coroutine_list_t     coroutine_queue; //等待执行的协程
        };
    //调度结构体,全局唯一 pthread_getspecific,pthread_setspecific实现
    coroutine_scheduler_t 
    //里面有一个主协程
    coroutine_scheduler_t *coroutine_scheduler_self(void)

4. coroutine_resume

    4.1 //将当前协程加入队列
        scheduler_queue_push(scheduler, co);
    4.2 //如果当前有正在运行
        if (scheduler->running_coroutine) {
            //如果当前有正在执行的协程,插入到队尾
            scheduler_queue_push(scheduler, scheduler->running_coroutine);
            //恢复当前协程继续执行
            coroutine_yield(scheduler->running_coroutine);
        } else {
            // 当前调度没有协程执行,恢复调度协程
            // 调度主协程
            coroutine_resume_im(co->scheduler->main_coroutine);

            //主协程入口方法
            // 从coroutine_queue pop一个协程出来执行
            coroutine_scheduler_main
        }

5. //执行协程

//由主协程的入口函数调度 协程
// COROUTINE_SUSPEND
void coroutine_resume_im(coroutine_t *co)
    //创建pre_context
    co->pre_context = malloc(sizeof(coroutine_ucontext_t));
    //保存现场
    //将当前寄存器的值写入co->pre_context
    coroutine_getcontext(co->pre_context);

    //创建co->context
    co->context = calloc(1, sizeof(coroutine_ucontext_t));

    //设置入口函数为pc
    //设置sp,fp
    coroutine_makecontext(co->context, (IMP)coroutine_main, co, (void *)co->stack_top);    
//设置参数
void coroutine_makecontext (coroutine_ucontext_t *ctx, IMP func, void *arg, void *stackTop)
{
    struct coroutine_ucontext_re *uctx = (struct coroutine_ucontext_re *)ctx;
    uintptr_t stackBegin = (uintptr_t)stackTop - sizeof(uintptr_t);
    uctx->GR.__fp = stackBegin;
    uctx->GR.__sp = stackBegin;
    uctx->GR.__x[0] = (uintptr_t)arg;
    uctx->GR.__pc = (uintptr_t)func;
}
//调用汇编 执行指令
coroutine_begin(co->context);

6. coroutine_yield

void coroutine_yield(coroutine_t *co){
    //保存现场,将寄存器的值写入oc->pre_context
    //并且设置状态,下次可以恢复调度
    co->status = COROUTINE_SUSPEND;
}

相关关键结构体
typedef struct coroutine_ucontext {
    uint64_t data[100];
} coroutine_ucontext_t;

struct coroutine_ucontext_re {
    struct GPRs {
        uint64_t __x[29]; // x0-x28
        uint64_t __fp;    // Frame pointer x29
        uint64_t __lr;    // Link register x30
        uint64_t __sp;    // Stack pointer x31
        uint64_t __pc;    // Program counter
        uint64_t padding; // 16-byte align, for cpsr
    } GR;
    double  VR[32];
};

//协程先保存当前寄存器的值到pre_context
//将寄存器的值写入pre_context coroutine_ucontext_t
extern int coroutine_getcontext (coroutine_ucontext_t *__ucp);

//恢复现场,将context的值读入寄存器,执行入口函数
//由coroutine_scheduler_main 唤醒协程执行
extern int coroutine_setcontext (coroutine_ucontext_t *__ucp);

//恢复现场,执行入口函数
extern int coroutine_begin (coroutine_ucontext_t *__ucp);
//汇编指令找到pc
ldr x9, [x0, #0x100] // restore pc into lr
//跳转到入口函数
ret x9

你可能感兴趣的:(cocore 阅读)